详细分析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实现的页内搜索代码
May 23 Javascript
帮助避免错误的Javascript陷阱清单
May 31 Javascript
js 判断checkbox是否选中的实现代码
Nov 23 Javascript
Javascript添加监听与删除监听用法详解
Dec 19 Javascript
原生javascript实现图片无缝滚动效果
Feb 12 Javascript
JS字符串按逗号和回车分隔的方法
Apr 25 Javascript
Vue中计算属性computed的示例解读
Jul 26 Javascript
javascript基于定时器实现进度条功能实例
Oct 13 Javascript
基于JavaScript实现简单的音频播放功能
Jan 07 Javascript
详解关于表格合并span-method方法的补充(表格数据由后台动态返回)
May 21 Javascript
selenium 反爬虫之跳过淘宝滑块验证功能的实现代码
Aug 27 Javascript
element-ui中dialog弹窗关闭按钮失效的解决
Sep 22 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
天津市收音机工业发展史
2021/03/04 无线电
4.与数据库的连接
2006/10/09 PHP
php通过array_shift()函数移除数组第一个元素的方法
2015/03/18 PHP
PHP7基于curl实现的上传图片功能
2018/05/11 PHP
表单项的name命名为submit、reset引起的问题
2007/12/22 Javascript
一个很酷的拖动层的js类,兼容IE及Firefox
2009/06/23 Javascript
Extjs407 getValue()和getRawValue()区别介绍
2013/05/21 Javascript
display和visibility的区别示例介绍
2014/02/26 Javascript
JQuery包裹DOM节点的方法
2015/06/11 Javascript
关于javascript中dataset的问题小结
2015/11/16 Javascript
javascript实现省市区三级联动下拉框菜单
2015/11/17 Javascript
Nodejs之TCP服务端与客户端聊天程序详解
2017/07/07 NodeJs
深入讲解xhr(XMLHttpRequest)/jsonp请求之abort
2017/07/26 Javascript
在Js页面通过POST传递参数跳转到新页面详解
2017/08/25 Javascript
Vue如何从1.0迁移到2.0
2017/10/19 Javascript
javascript计算对象长度的方法
2017/10/25 Javascript
vue2.x+webpack快速搭建前端项目框架详解
2017/11/30 Javascript
node.js将MongoDB数据同步到MySQL的步骤
2017/12/10 Javascript
Node.js中读取TXT文件内容fs.readFile()用法
2018/10/10 Javascript
JavaScript基于数组实现的栈与队列操作示例
2018/12/22 Javascript
bootstrap中的导航条实例代码详解
2019/05/20 Javascript
微信小程序动态评分展示/五角星展示/半颗星展示/自定义长度展示功能的实现
2020/07/22 Javascript
[45:06]完美世界DOTA2联赛PWL S2 Magma vs InkIce 第二场 11.28
2020/12/02 DOTA
python使用ctypes模块调用windowsapi获取系统版本示例
2014/04/17 Python
Python中第三方库Requests库的高级用法详解
2017/03/12 Python
基于Python列表解析(列表推导式)
2018/06/23 Python
NLTK 3.2.4 环境搭建教程
2018/09/19 Python
python滑块验证码的破解实现
2019/11/10 Python
通过Python pyecharts输出保存图片代码实例
2020/11/25 Python
Yahoo的PHP面试题
2014/05/26 面试题
以下为Windows NT 下的32 位C++程序,请计算sizeof 的值
2016/12/07 面试题
物业门卫岗位职责
2013/12/28 职场文书
tensorflow学习笔记之tfrecord文件的生成与读取
2021/03/31 Python
Python使用sql语句对mysql数据库多条件模糊查询的思路详解
2021/04/12 Python
SQL Server中交叉联接的用法详解
2021/04/22 SQL Server
Pandas||过滤缺失数据||pd.dropna()函数的用法说明
2021/05/14 Python