详细分析Node.js 多进程


Posted in Javascript onJune 22, 2020

我们都知道 Node.js 是以单线程的模式运行的,但它使用的是事件驱动来处理并发,这样有助于我们在多核 cpu 的系统上创建多个子进程,从而提高性能。

每个子进程总是带有三个流对象:child.stdin, child.stdout 和child.stderr。他们可能会共享父进程的 stdio 流,或者也可以是独立的被导流的流对象。

Node 提供了 child_process 模块来创建子进程,方法有:

  • exec - child_process.exec 使用子进程执行命令,缓存子进程的输出,并将子进程的输出以回调函数参数的形式返回。
  • spawn - child_process.spawn 使用指定的命令行参数创建新进程。
  • fork - child_process.fork 是 spawn()的特殊形式,用于在子进程中运行的模块,如 fork('./son.js') 相当于 spawn('node', ['./son.js']) 。与spawn方法不同的是,fork会在父进程与子进程之间,建立一个通信管道,用于进程之间的通信。

exec() 方法

child_process.exec 使用子进程执行命令,缓存子进程的输出,并将子进程的输出以回调函数参数的形式返回。

语法如下所示:

child_process.exec(command[, options], callback)

参数

参数说明如下:

command: 字符串, 将要运行的命令,参数使用空格隔开

options :对象,可以是:

  • cwd ,字符串,子进程的当前工作目录
  • env,对象 环境变量键值对
  • encoding ,字符串,字符编码(默认: 'utf8')
  • shell ,字符串,将要执行命令的 Shell(默认: 在 UNIX 中为/bin/sh, 在 Windows 中为cmd.exe, Shell 应当能识别 -c开关在 UNIX 中,或 /s /c 在 Windows 中。 在Windows 中,命令行解析应当能兼容cmd.exe)
  • timeout,数字,超时时间(默认: 0)
  • maxBuffer,数字, 在 stdout 或 stderr 中允许存在的最大缓冲(二进制),如果超出那么子进程将会被杀死 (默认: 200*1024)
  • killSignal ,字符串,结束信号(默认:'SIGTERM')
  • uid,数字,设置用户进程的 ID
  • gid,数字,设置进程组的 ID

callback :回调函数,包含三个参数error, stdout 和 stderr。

exec() 方法返回最大的缓冲区,并等待进程结束,一次性返回缓冲区的内容。

实例

让我们创建两个 js 文件 support.js 和 master.js。

support.js 文件代码:

console.log("进程 " + process.argv[2] + " 执行。" );

master.js 文件代码:

const fs = require('fs');
const child_process = require('child_process');
 
for(var i=0; i<3; i++) {
  var workerProcess = child_process.exec('node support.js '+i, function (error, stdout, stderr) {
    if (error) {
      console.log(error.stack);
      console.log('Error code: '+error.code);
      console.log('Signal received: '+error.signal);
    }
    console.log('stdout: ' + stdout);
    console.log('stderr: ' + stderr);
  });
 
  workerProcess.on('exit', function (code) {
    console.log('子进程已退出,退出码 '+code);
  });
}

执行以上代码,输出结果为:

$ node master.js
子进程已退出,退出码 0
stdout: 进程 1 执行。

stderr:
子进程已退出,退出码 0
stdout: 进程 0 执行。

stderr:
子进程已退出,退出码 0
stdout: 进程 2 执行。

stderr:

spawn() 方法

child_process.spawn 使用指定的命令行参数创建新进程,语法格式如下:

child_process.spawn(command[, args][, options])

参数

参数说明如下:

command: 将要运行的命令

args: Array 字符串参数数组

options Object

  • cwd String 子进程的当前工作目录
  • env Object 环境变量键值对
  • stdio Array|String 子进程的 stdio 配置
  • detached Boolean 这个子进程将会变成进程组的领导
  • uid Number 设置用户进程的 ID
  • gid Number 设置进程组的 ID

spawn() 方法返回流 (stdout & stderr),在进程返回大量数据时使用。进程一旦开始执行时 spawn() 就开始接收响应。

实例

让我们创建两个 js 文件 support.js 和 master.js。

support.js 文件代码:

console.log("进程 " + process.argv[2] + " 执行。" );

master.js 文件代码:

const fs = require('fs');
const child_process = require('child_process');
 
for(var i=0; i<3; i++) {
  var workerProcess = child_process.spawn('node', ['support.js', i]);
 
  workerProcess.stdout.on('data', function (data) {
   console.log('stdout: ' + data);
  });
 
  workerProcess.stderr.on('data', function (data) {
   console.log('stderr: ' + data);
  });
 
  workerProcess.on('close', function (code) {
   console.log('子进程已退出,退出码 '+code);
  });
}

执行以上代码,输出结果为:

$ node master.js stdout: 进程 0 执行。

子进程已退出,退出码 0
stdout: 进程 1 执行。

子进程已退出,退出码 0
stdout: 进程 2 执行。

子进程已退出,退出码 0

fork 方法

child_process.fork 是 spawn() 方法的特殊形式,用于创建进程,语法格式如下:

child_process.fork(modulePath[, args][, options])

参数

参数说明如下:

modulePath: String,将要在子进程中运行的模块

args: Array 字符串参数数组

options:Object

  • cwd String 子进程的当前工作目录
  • env Object 环境变量键值对
  • execPath String 创建子进程的可执行文件
  • execArgv Array 子进程的可执行文件的字符串参数数组(默认: process.execArgv)
  • silent Boolean 如果为true,子进程的stdin,stdout和stderr将会被关联至父进程,否则,它们将会从父进程中继承。(默认为:false)
  • uid Number 设置用户进程的 ID
  • gid Number 设置进程组的 ID

返回的对象除了拥有ChildProcess实例的所有方法,还有一个内建的通信信道。

实例

让我们创建两个 js 文件 support.js 和 master.js。

support.js 文件代码:

console.log("进程 " + process.argv[2] + " 执行。" );

master.js 文件代码:

const fs = require('fs');
const child_process = require('child_process');
 
for(var i=0; i<3; i++) {
  var worker_process = child_process.fork("support.js", [i]);  
 
  worker_process.on('close', function (code) {
   console.log('子进程已退出,退出码 ' + code);
  });
}

执行以上代码,输出结果为:

$ node master.js
进程 0 执行。
子进程已退出,退出码 0
进程 1 执行。
子进程已退出,退出码 0
进程 2 执行。
子进程已退出,退出码 0

以上就是详细分析Node.js 多进程的详细内容,更多关于Node.js 多进程的资料请关注三水点靠木其它相关文章!

Javascript 相关文章推荐
JavaScript Undefined,Null类型和NaN值区别
Oct 22 Javascript
jquery操作下拉列表、文本框、复选框、单选框集合(收藏)
Jan 08 Javascript
通过网页查看JS源码中汉字显示乱码的解决方法
Oct 26 Javascript
浅谈js中startsWith 函数不能在任何浏览器兼容的问题
Mar 01 Javascript
详谈jQuery中使用attr(), prop(), val()获取value的异同
Apr 25 jQuery
详解Vue2.X的路由管理记录之 钩子函数(切割流水线)
May 02 Javascript
vue cli使用绝对路径引用图片问题的解决
Dec 06 Javascript
基于element-ui的rules中正则表达式
Sep 04 Javascript
JavaScript中的&quot;=、==、===&quot;区别讲解
Jan 22 Javascript
详解vue中this.$emit()的返回值是什么
Apr 07 Javascript
微信小程序中data-key属性之数据传输(经验总结)
Aug 22 Javascript
JavaScript实现酷炫的鼠标拖尾特效
Feb 18 Javascript
详细分析vue响应式原理
Jun 22 #Javascript
Vue循环遍历选项赋值到对应控件的实现方法
Jun 22 #Javascript
如何解决jQuery 和其他JS库的冲突
Jun 22 #jQuery
解决Vue 给mapState中定义的属性赋值报错的问题
Jun 22 #Javascript
支付宝小程序实现省市区三级联动
Jun 21 #Javascript
微信小程序实现canvas分享朋友圈海报
Jun 21 #Javascript
微信小程序实现选择地址省市区三级联动
Jun 21 #Javascript
You might like
通过5个php实例细致说明传值与传引用的区别
2012/08/08 PHP
php正则判断是否为合法身份证号的方法
2017/03/16 PHP
PHP 进度条函数的简单实例
2017/09/19 PHP
Laravel框架使用Seeder实现自动填充数据功能
2018/06/13 PHP
PHP实现的微信APP支付功能示例【基于TP5框架】
2019/09/16 PHP
php设计模式之正面模式实例分析【星际争霸游戏案例】
2020/03/24 PHP
js 屏蔽鼠标右键脚本附破解方法
2009/12/03 Javascript
分享十五个最佳jQuery 幻灯插件和教程
2010/03/27 Javascript
JavaScript中的apply()方法和call()方法使用介绍
2012/07/25 Javascript
jQuery extend 的简单实例
2013/09/18 Javascript
js 获取元素在页面上的偏移量的方法汇总
2015/04/13 Javascript
jquery滚动到顶部底部代码
2015/04/20 Javascript
浅谈jQuery构造函数分析
2015/05/11 Javascript
javascript框架设计之种子模块
2015/06/23 Javascript
jQuery获取table行数并输出单元格内容的实现方法
2016/06/30 Javascript
AngularJS 视图详解及示例代码
2016/08/17 Javascript
BootStrap轻松实现微信页面开发代码分享
2016/10/21 Javascript
快速实现jQuery多级菜单效果
2017/02/01 Javascript
JS数组搜索之折半搜索实现方法分析
2017/03/27 Javascript
jQuery实现简单漂亮的Nav导航菜单效果
2017/03/29 jQuery
微信小程序图片横向左右滑动案例
2017/05/19 Javascript
Node.js使用Angular简单示例
2018/05/11 Javascript
JavaScript 2018 中即将迎来的新功能
2018/09/21 Javascript
在vue-cli中引入lodash.js并使用详解
2019/11/13 Javascript
[01:34]传奇从这开始 2016国际邀请赛中国区预选赛震撼开启
2016/06/26 DOTA
python读文件逐行处理的示例代码分享
2013/12/27 Python
详解Python3中的 input() 函数
2020/03/18 Python
jupyter notebook清除输出方式
2020/04/10 Python
详解h5页面在不同ios设备上的问题总结
2019/03/01 HTML / CSS
美国领先的家庭智能音响系统品牌:Sonos
2018/07/20 全球购物
网络工程师个人的自我评价范文
2013/10/01 职场文书
餐饮收银员岗位职责
2014/02/07 职场文书
实习推荐信
2014/05/10 职场文书
党员承诺书格式
2014/05/21 职场文书
部队个人年终总结
2015/03/02 职场文书
争先创优个人总结
2015/03/04 职场文书