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服务器(7):阻塞操作的实现
Dec 18 NodeJs
快速掌握Node.js之Window下配置NodeJs环境
Mar 21 NodeJs
nodejs微信公众号支付开发
Sep 19 NodeJs
Nodejs下DNS缓存问题浅析
Nov 16 NodeJs
Nodejs回调加超时限制两种实现方法
Jun 09 NodeJs
理解nodejs的stream和pipe机制的原理和实现
Aug 12 NodeJs
nodejs实现OAuth2.0授权服务认证
Dec 27 NodeJs
Mac下通过brew安装指定版本的nodejs教程
May 17 NodeJs
nodejs中用npm初始化来创建package.json的实例讲解
Oct 10 NodeJs
nodejs实现百度舆情接口应用示例
Feb 07 NodeJs
NodeJS模块Buffer原理及使用方法解析
Nov 11 NodeJs
nodejs利用readline提示输入内容实例代码
Jul 15 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学习资源和链接.
2006/12/05 PHP
phpQuery占用内存过多的处理方法
2013/11/13 PHP
phplot生成图片类用法详解
2015/01/06 PHP
PHP学习笔记(一):基本语法之标记、空白、和注释
2015/04/17 PHP
Laravel 不同生产环境服务器的判断实践
2019/10/15 PHP
打开新窗口关闭当前页面不弹出关闭提示js代码
2013/03/18 Javascript
原生js ActiveXObject获取execl里面的值
2013/11/01 Javascript
JavaScript中实现Map的示例代码
2015/09/09 Javascript
微信小程序 tabs选项卡效果的实现
2017/01/05 Javascript
基于daterangepicker日历插件使用参数注意的问题
2017/08/10 Javascript
AngularJS遍历获取数组元素的方法示例
2017/11/11 Javascript
微信小程序封装的HTTP请求示例【附升级版】
2019/05/11 Javascript
Vue安装浏览器开发工具的步骤详解
2019/05/12 Javascript
JavaScript对象字面量和构造函数原理与用法详解
2020/04/18 Javascript
win7安装python生成随机数代码分享
2013/12/27 Python
Python中使用异常处理来判断运行的操作系统平台方法
2015/01/22 Python
pygame学习笔记(5):游戏精灵
2015/04/15 Python
Python的Django框架可适配的各种数据库介绍
2015/07/15 Python
Python查找两个有序列表中位数的方法【基于归并算法】
2018/04/20 Python
Python Django 命名空间模式的实现
2019/08/09 Python
python 微信好友特征数据分析及可视化
2020/01/07 Python
python爬虫开发之使用python爬虫库requests,urllib与今日头条搜索功能爬取搜索内容实例
2020/03/10 Python
jupyter notebook oepncv 显示一张图像的实现
2020/04/24 Python
CSS3实现复选框动画特效示例代码
2016/09/27 HTML / CSS
HTML5几个设计和修改的页面范例分享
2015/09/29 HTML / CSS
西班牙拥有最佳品牌的动物商店:Animalear.com
2018/01/05 全球购物
Nike比利时官网:Nike.com (BE)
2019/02/07 全球购物
学生党员思想汇报范文
2014/01/09 职场文书
职工运动会感言
2014/02/07 职场文书
数控技校生自我鉴定
2014/04/19 职场文书
健康家庭事迹材料
2014/05/02 职场文书
八项规定对照检查材料
2014/08/31 职场文书
房屋出租委托书格式
2014/09/23 职场文书
办公用品质量保证书
2015/05/11 职场文书
OpenCV-Python模板匹配人眼的实例
2021/06/08 Python
Java中使用Filter过滤器的方法
2021/06/28 Java/Android