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中的VM模块详解
May 06 NodeJs
Nodejs获取网络数据并生成Excel表格
Mar 31 NodeJs
nodejs基础应用
Feb 03 NodeJs
nodejs爬虫遇到的乱码问题汇总
Apr 07 NodeJs
详解nodejs模板引擎制作
Jun 14 NodeJs
nodejs中解决异步嵌套循环和循环嵌套异步的问题
Jul 12 NodeJs
详解nodejs通过代理(proxy)发送http请求(request)
Sep 22 NodeJs
详解IWinter 一个路由转控制器的 Nodejs 库
Nov 15 NodeJs
Nodejs模块载入运行原理
Feb 23 NodeJs
nodejs实现套接字服务功能详解
Jun 21 NodeJs
用Electron写个带界面的nodejs爬虫的实现方法
Jan 29 NodeJs
nodejs如何在package.json中设置多条启动命令
Mar 16 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 mssql 时间格式问题
2009/01/13 PHP
PHP-CGI进程CPU 100% 与 file_get_contents 函数的关系分析
2011/08/15 PHP
yii操作session实例简介
2014/07/31 PHP
PHP中的traits简单使用实例
2015/05/13 PHP
PHP反射机制原理与用法详解
2017/02/15 PHP
php注册审核重点解析(数据访问)
2017/05/23 PHP
关于全局变量和局部变量的那些事
2013/01/11 Javascript
js读写(删除)Cookie实例详解
2013/04/17 Javascript
jQuery隔行变色与普通JS写法的对比
2013/04/21 Javascript
js实现的四级左侧网站分类菜单实例
2015/05/06 Javascript
jQuery实现响应鼠标事件的图片透明效果【附demo源码下载】
2016/06/16 Javascript
基于jQuery实现左侧菜单栏可折叠功能
2016/12/27 Javascript
JS+WCF实现进度条实时监测数据加载量的方法详解
2017/12/19 Javascript
使用Python读写及压缩和解压缩文件的示例
2016/07/08 Python
Python 序列的方法总结
2016/10/18 Python
利用Pandas 创建空的DataFrame方法
2018/04/08 Python
PyQt5每天必学之工具提示功能
2018/04/19 Python
Python 使用PIL中的resize进行缩放的实例讲解
2018/08/03 Python
python实现计数排序与桶排序实例代码
2019/03/28 Python
Python画图高斯分布的示例
2019/07/10 Python
详解基于Facecognition+Opencv快速搭建人脸识别及跟踪应用
2021/01/21 Python
戴森西班牙官网:Dyson西班牙
2020/02/04 全球购物
端口镜像是怎么实现的
2014/03/25 面试题
Java程序员面试题
2013/07/15 面试题
Delphi工程师笔试题
2013/09/21 面试题
最新奶茶店创业计划书范文
2014/02/08 职场文书
秋游活动策划方案
2014/02/16 职场文书
2014全国两会大学生学习心得体会
2014/03/10 职场文书
2014年个人委托书范本
2014/10/13 职场文书
债务追讨授权委托书范本
2014/10/16 职场文书
2015年审计人员工作总结
2015/05/26 职场文书
教师年度考核自我评鉴
2015/08/11 职场文书
2019求职信:应届生求职信范文
2019/04/24 职场文书
python第三方网页解析器 lxml 扩展库与 xpath 的使用方法
2021/04/06 Python
python基础之文件操作
2021/10/24 Python
MySQL中CURRENT_TIMESTAMP的使用方式
2021/11/27 MySQL