详细分析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 相关文章推荐
跟着JQuery API学Jquery 之二 属性
Apr 09 Javascript
JavaScript高级程序设计 读书笔记之十一 内置对象Global
Mar 07 Javascript
BOOTSTRAP时间控件显示在模态框下面的bug修复
Feb 05 Javascript
jQuery实现复选框成对选择及对应取消的方法
Mar 03 Javascript
Javascript 正则表达式实现为数字添加千位分隔符
Mar 10 Javascript
JS获取子窗口中返回的数据实现方法
May 28 Javascript
Vue方法与事件处理器详解
Dec 01 Javascript
angular过滤器实现排序功能
Jun 27 Javascript
jQuery列表检索功能实现代码
Jul 17 jQuery
jQuery:unbind方法的使用详解
Aug 14 jQuery
简单了解常用的JavaScript 库
Jul 16 Javascript
PHP 502bad gateway原因及解决方案
Nov 13 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
根德YB400的电路分析
2021/03/02 无线电
PHP的FTP学习(一)[转自奥索]
2006/10/09 PHP
PHP产生随机字符串函数
2006/12/06 PHP
PHP学习笔记之二
2011/01/17 PHP
PHP实现广度优先搜索算法(BFS,Broad First Search)详解
2017/09/16 PHP
PHP8.0新功能之Match表达式的使用
2020/07/19 PHP
JSON扫盲帖 JSON.as类教程
2009/02/16 Javascript
在chrome中window.onload事件的一些问题
2010/03/01 Javascript
JavaScript常用对象的方法和属性小结
2012/01/24 Javascript
angular6.x中ngTemplateOutlet指令的使用示例
2018/08/09 Javascript
vue自定义全局共用函数详解
2018/09/18 Javascript
微信小程序封装的HTTP请求示例【附升级版】
2019/05/11 Javascript
vue实现表单录入小案例
2019/09/27 Javascript
Vue 样式切换及三元判断样式关联操作
2020/08/09 Javascript
python实现划词翻译
2020/04/23 Python
python使用pil生成图片验证码的方法
2015/05/08 Python
python用10行代码实现对黄色图片的检测功能
2015/08/10 Python
Python爬虫实战:分析《战狼2》豆瓣影评
2018/03/26 Python
python list转矩阵的实例讲解
2018/08/04 Python
python游戏地图最短路径求解
2019/01/16 Python
HTML5 表单验证失败的提示语问题
2017/07/13 HTML / CSS
html5实现九宫格抽奖可固定抽中某项奖品
2020/06/15 HTML / CSS
JD Sports德国官网:英国领先的运动鞋和运动服饰零售商
2018/02/26 全球购物
Mio Skincare法国官网:身体紧致及孕期身体护理
2018/04/04 全球购物
英国在线自行车店:Merlin Cycles
2018/08/20 全球购物
Muziker英国:中欧最大的音乐家商店
2020/02/05 全球购物
小学美术教学反思
2014/02/01 职场文书
文艺节目主持词
2015/07/06 职场文书
2016年“六一儿童节”校园广播稿
2015/12/17 职场文书
python tkinter模块的简单使用
2021/04/07 Python
MySQL5.7并行复制原理及实现
2021/06/03 MySQL
你知道哪几种MYSQL的连接查询
2021/06/03 MySQL
vue项目中的支付功能实现(微信支付和支付宝支付)
2022/02/18 Vue.js
mysql使用FIND_IN_SET和group_concat两个方法查询上下级机构
2022/04/20 MySQL
解决Python保存文件名太长OSError: [Errno 36] File name too long
2022/05/11 Python
springboot 全局异常处理和统一响应对象的处理方式
2022/06/28 Java/Android