Nodejs极简入门教程(三):进程


Posted in NodeJs onOctober 27, 2014

Node 虽然自身存在多个线程,但是运行在 v8 上的 JavaScript 是单线程的。Node 的 child_process 模块用于创建子进程,我们可以通过子进程充分利用 CPU。范例:

var fork = require('child_process').fork;

// 获取当前机器的 CPU 数量

var cpus = require('os').cpus();

for (var i = 0; i < cpus.length; i++) {

    // 生成新进程

    fork('./worker.js');

}

这里了解一下包括 fork 在内的几个进程创建方法:

1.spawn(command, [args], [options]),启动一个新进程来执行命令 command,args 为命令行参数
2.exec(command, [options], callback),启动一个新进程来执行命令 command,callback 用于在进程结束时获取标准输入、标准输出,以及错误信息
3.execFile(file, [args], [options], [callback]),启动一个新进程来执行可执行文件 file,callback 用于在进程结束时获取标准输入、标准输出,以及错误信息
4.fork(modulePath, [args], [options]),启动一个新进程来执行一个 JavaScript 文件模块,这时候创建的是 Node 子进程

Node 进程间通信

父进程

// parent.js

var fork = require('child_process').fork;

// fork 返回子进程对象 n

var n = fork('./child.js');

// 处理事件 message

n.on('message', function(m) {

    // 收到子进程发送的消息

    console.log('got message: ' + m);

});

 

// 向子进程发送消息

n.send({hello: 'world'});

子进程

// child.js

// 处理事件 message

process.on('message', function(m) {

    console.log('got message: ' + m);

});

 

// process 存在 send 方法,用于向父进程发送消息

process.send({foo: 'bar'});

需要注意的是,这里的 send 方法是同步的,因此不建议用于发送大量的数据(可以使用 pipe 来代替,详细见:http://nodejs.org/api/all.html#child_process_child_process_spawn_command_args_options)。
特殊的情况,消息中 cmd 属性值包含 NODE_ 前缀(例如:{cmd: ‘NODE_foo'} 消息),那么此消息不会被提交到 message 事件(而是 internalMessage 事件),它们被 Node 内部使用。

send 方法的原型为:

send(message, [sendHandle])

这里,sendHandle(handle)可以被用于发送:

1.net.Native,原生的 C++ TCP socket 或者管道
2.net.Server,TCP 服务器
3.net.Socket,TCP socket
4.dgram.Native,原生的 C++ UDP socket
5.dgram.Socket,UDP socket

send 发送 sendHandle 时实际上不是(也不能)直接发送 JavaScript 对象,而是发送文件描述符(最终以 JSON 字符串发送),其他进程能够通过这个文件描述符还原出对应对象。

现在看一个例子:

父进程

// parent.js

var fork = require('child_process').fork;

 

var n = fork('./child.js');

 

var server = require('net').createServer();

server.listen(7000, function() {

    // 发送 TCP server 到子进程

    n.send('server', server);

}).on('connection', function() {

    console.log('connection - parent');

});

子进程

process.on('message', function(m, h) {

    if (m === 'server') {

        h.on('connection', function() {

            console.log('connection - child');

        });

    }

});

通过端口 7000 访问此程序,得到输出可能为 connection ? parent 也可能得到输出 connection ? child。这里子进程和父进程同时监听了端口 7000。通常来说,多个进程监听同一个端口会引起 EADDRINUSE 的异常,而此例的情况是,不同的两个进程使用了相同的文件描述符,且 Node 底层在监听端口时对 socket 设置了 SO_REUSEADDR 选项,这使得此 socket 可以在不同的进程间复用。在多个进程监听同一个端口时,同一时刻文件描述符只能被一个进程使用,这些进程对 socket 的使用是抢占式的。

cluster 模块

在 Node 的 v0.8 新增了 cluster 模块,通过 cluster 模块能够轻松的在一台物理机器上构建一组监听相同端口的进程。范例:

var cluster = require('cluster');

var http = require('http');

var numCPUs = require('os').cpus().length;

 

// 检查进程是否是 master 进程

if (cluster.isMaster) {

    for (var i = 0; i < numCPUs; ++i)

        // 生成新的 worker 进程(只有 master 进程才可以调用)

        cluster.fork();

 

    cluster.on('exit', function(worker, code, signal) {

        console.log('worker ' + worker.process.pid + ' died');

    });

} else {

    http.createServer(function(req, res) {

        res.writeHead(200);

        res.end('hello world\n');

    }).listen(8000);

}

我们在 worker 进程中调用 listen 方法,监听请求将会传递给 master 进程。如果 master 进程已经存在一个正在监听的 server 符合 worker 进程的要求,那么此 server 的 handle 将会传递给 worker,如果不存在,master 进程则会创建一个,然后将 handle 传递给 worker 进程。

更多详细的关于 cluster 的文档:http://www.nodejs.org/api/cluster.html

NodeJs 相关文章推荐
基于NodeJS的前后端分离的思考与实践(四)安全问题解决方案
Sep 26 NodeJs
nodejs开发环境配置与使用
Nov 17 NodeJs
Jquery通过ajax请求NodeJS返回json数据实例
Nov 08 NodeJs
nodejs开发——express路由与中间件
Mar 24 NodeJs
详解nodejs实现本地上传图片并预览功能(express4.0+)
Jun 28 NodeJs
Express+Nodejs 下的登录拦截实现代码
Jul 01 NodeJs
nodejs使用http模块发送get与post请求的方法示例
Jan 08 NodeJs
Nodejs下使用gm圆形裁剪并合成图片的示例
Feb 22 NodeJs
详解Nodejs get获取远程服务器接口数据
Mar 26 NodeJs
详解利用nodejs对本地json文件进行增删改查
Sep 20 NodeJs
nodejs使用socket5进行代理请求的实现
Feb 21 NodeJs
nodejs中使用worker_threads来创建新的线程的方法
Jan 22 NodeJs
Nodejs极简入门教程(二):定时器
Oct 25 #NodeJs
Nodejs极简入门教程(一):模块机制
Oct 25 #NodeJs
基于NodeJS的前后端分离的思考与实践(六)Nginx + Node.js + Java 的软件栈部署实践
Sep 26 #NodeJs
基于NodeJS的前后端分离的思考与实践(五)多终端适配
Sep 26 #NodeJs
基于NodeJS的前后端分离的思考与实践(四)安全问题解决方案
Sep 26 #NodeJs
基于NodeJS的前后端分离的思考与实践(三)轻量级的接口配置建模框架
Sep 26 #NodeJs
基于NodeJS的前后端分离的思考与实践(二)模版探索
Sep 26 #NodeJs
You might like
PHP中“简单工厂模式”实例代码讲解
2012/09/04 PHP
php自动更新版权信息显示的方法
2015/06/19 PHP
[原创]php正则删除html代码中class样式属性的方法
2017/05/24 PHP
PHP实现一个多功能购物网站的案例
2017/09/13 PHP
在云虚拟主机部署thinkphp5项目的步骤详解
2017/12/21 PHP
对象特征检测法判断浏览器对javascript对象的支持
2009/07/25 Javascript
javascript 类定义的4种方法
2009/09/12 Javascript
javascript 从if else 到 switch case 再到抽象
2010/07/17 Javascript
屏蔽script注入小例子
2013/11/12 Javascript
jQuery打印指定区域Html页面并自动分页
2014/07/04 Javascript
node.js中的url.format方法使用说明
2014/12/10 Javascript
简单谈谈jQuery(function(){})与(function(){})(jQuery)
2014/12/19 Javascript
JS实现定时自动关闭DIV层提示框的方法
2015/05/11 Javascript
AngularJS中过滤器的使用与自定义实例代码
2016/09/17 Javascript
深入探究angular2 UI组件之primeNG用法
2017/07/26 Javascript
微信小程序点击view动态添加样式过程解析
2020/01/21 Javascript
js实现省级联动(数据结构优化)
2020/07/17 Javascript
vue 虚拟DOM的原理
2020/10/03 Javascript
[01:23:59]2018DOTA2亚洲邀请赛 4.1 小组赛 B组 VP vs Secret
2018/04/03 DOTA
python操作mysql中文显示乱码的解决方法
2014/10/11 Python
Keras之fit_generator与train_on_batch用法
2020/06/17 Python
opencv 形态学变换(开运算,闭运算,梯度运算)
2020/07/07 Python
Python  word实现读取及导出代码解析
2020/07/09 Python
python实现最短路径的实例方法
2020/07/19 Python
中国跨境电子商务网站:NewFrog
2018/03/10 全球购物
英国领先的酒杯和水晶玻璃器皿制造商:Dartington Crystal
2019/06/23 全球购物
乌克兰巴士票购买网站:inBus
2021/03/12 全球购物
行政助理岗位职责
2013/11/10 职场文书
新郎婚宴答谢词
2014/01/19 职场文书
先进集体事迹材料
2014/02/17 职场文书
个人承诺书怎么写
2014/05/24 职场文书
生活部的活动方案
2014/08/19 职场文书
2015年思想品德教学工作总结
2015/07/22 职场文书
2016年社区党支部公开承诺书
2016/03/25 职场文书
七年级作文之冬景
2019/11/07 职场文书
MySQL数据库 任意ip连接方法
2022/05/20 MySQL