详细分析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 相关文章推荐
js 取时间差去掉周六周日实现代码
Dec 25 Javascript
jQuery使用andSelf()来包含之前的选择集
May 19 Javascript
node.js中的fs.unlink方法使用说明
Dec 15 Javascript
javascript的switch用法注意事项分析
Feb 02 Javascript
javascript数字验证的实例代码(推荐)
Aug 20 Javascript
js实现3d悬浮效果
Feb 16 Javascript
jQuery实现验证表单密码一致性及正则表达式验证邮箱、手机号的方法
Dec 05 jQuery
浅析Visual Studio Code断点调试Vue
Feb 27 Javascript
Angular @HostBinding()和@HostListener()用法
Mar 05 Javascript
解决vuejs项目里css引用背景图片不能显示的问题
Sep 13 Javascript
vue项目打包上传github并制作预览链接(pages)
Apr 19 Javascript
bootstrap-closable-tab可实现关闭的tab标签页插件
Aug 09 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
单一index.php实现PHP任意层级文件夹遍历(Zjmainstay原创)
2012/07/31 PHP
Laravel 5框架学习之模型、控制器、视图基础流程
2015/04/08 PHP
yii2.0实现创建简单widgets示例
2016/07/18 PHP
PHP中检索字符串的方法分析【strstr与substr_count方法】
2017/02/17 PHP
PHP插件PHPMailer发送邮件功能
2017/02/28 PHP
Aptana调试javascript图解教程
2009/11/30 Javascript
jQuery获取文本节点之 text()/val()/html() 方法区别
2011/03/01 Javascript
原生js 秒表实现代码
2012/07/24 Javascript
教你用AngularJS框架一行JS代码实现控件验证效果
2014/06/23 Javascript
常用的JavaScript模板引擎介绍
2015/02/28 Javascript
谈谈我对JavaScript中typeof和instanceof的深入理解
2015/12/25 Javascript
D3.js实现文本的换行详解
2016/10/14 Javascript
vue.js全局API之nextTick全面解析
2017/07/07 Javascript
parabola.js抛物线与加入购物车效果的示例代码
2017/10/25 Javascript
ES6 系列之 Generator 的自动执行的方法示例
2018/10/19 Javascript
Vue项目报错:Uncaught SyntaxError: Unexpected token
2018/11/10 Javascript
jQuery实现的老虎机跑动效果示例
2018/12/29 jQuery
mpvue性能优化实战技巧(小结)
2019/04/17 Javascript
JS中的算法与数据结构之常见排序(Sort)算法详解
2019/08/16 Javascript
Node配合WebSocket做多文件下载以及进度回传
2019/11/07 Javascript
jquery实现手风琴案例
2020/05/04 jQuery
js实现直播点击飘心效果
2020/08/19 Javascript
[43:58]DOTA2上海特级锦标赛C组败者赛 Newbee VS Archon第二局
2016/02/27 DOTA
Python yield 使用浅析
2015/05/28 Python
用Python逐行分析文件方法
2019/01/28 Python
python实现简单日志记录库glog的使用
2019/12/13 Python
Python2.x与3​​.x版本有哪些区别
2020/07/09 Python
Python模块zipfile原理及使用方法详解
2020/08/04 Python
荷兰网上鞋店:Ziengs.nl
2017/01/02 全球购物
UGG澳洲官网:UGG Australia
2018/04/26 全球购物
企业总经理职责
2014/02/02 职场文书
教师网络培训感言
2014/03/09 职场文书
2014教师党员自我评议总结
2014/09/19 职场文书
新闻稿件写作技巧
2015/07/18 职场文书
MyBatis自定义SQL拦截器示例详解
2021/10/24 Java/Android
MySQL图形化管理工具Navicat安装步骤
2021/12/04 MySQL