我的编程空间,编程开发者的网络收藏夹
学习永远不晚

深入理解Node.js中的进程管理

短信预约 -IT技能 免费直播动态提醒
省份

北京

  • 北京
  • 上海
  • 天津
  • 重庆
  • 河北
  • 山东
  • 辽宁
  • 黑龙江
  • 吉林
  • 甘肃
  • 青海
  • 河南
  • 江苏
  • 湖北
  • 湖南
  • 江西
  • 浙江
  • 广东
  • 云南
  • 福建
  • 海南
  • 山西
  • 四川
  • 陕西
  • 贵州
  • 安徽
  • 广西
  • 内蒙
  • 西藏
  • 新疆
  • 宁夏
  • 兵团
手机号立即预约

请填写图片验证码后获取短信验证码

看不清楚,换张图片

免费获取短信验证码

深入理解Node.js中的进程管理

前言

本文主要对 Node.js 中进程管理相关的东西做一个简单介绍,包括 process 对象、child_process 模块和cluster 模块,详细的 API 可以查看官方文档,下面来看看详细的介绍吧。

Process 对象

process 是 Node.js 的一个全局对象,可以在任何地方直接使用而不需要 require 命令加载。process 对象提供了 当前 node 进程 的命令行参数、标准输入输出、运行环境和运行状态等信息。

常用属性

argv

process.argv 属性返回一个数组,第一个元素是 node,第二个元素是脚本文件名称,其余成员是脚本文件的参数。


$ node process-2.js one two=three four

0: /usr/local/bin/node
1: /Users/mjr/work/node/process-2.js
2: one
3: two=three
4: four

env

process.env 返回一个对象,包含了当前 Shell 的所有环境变量,比如:


{
 TERM: 'xterm-256color',
 SHELL: '/bin/zsh',
 USER: 'huangtengfei',
 PATH: '~/.bin/:/usr/bin:/bin:/usr/sbin:/sbin:/usr/local/bin',
 PWD: '/Users/huangtengfei',
 HOME: '/Users/huangtengfei'
}

这个属性通常的使用场景是,新建一个 NODE_ENV 变量,用来确定当前所处的开发阶段,生成阶段设为 production,开发阶段设为 develop ,然后在脚本中读取 process.env.NODE_ENV 再做相应处理即可。

运行脚本时可以这样改变环境变量:


$ export NODE_ENV=production && node app.js
# 或者
$ NODE_ENV=production node app.js

stdin/stdout

process.stdin 指向标准输入(键盘到缓冲区里的东西),返回一个可读的流:


process.stdin.setEncoding('utf8');

process.stdin.on('readable', () => {
 var chunk = process.stdin.read();
 if (chunk !== null) {
 process.stdout.write(`data: ${chunk}`);
 }
});

process.stdin.on('end', () => {
 process.stdout.write('end');
});

process.stdout 指向标准输出(向用户显示内容),返回一个可写的流:


const fs = require('fs');

fs.createReadStream('wow.txt')
 .pipe(process.stdout);

常用方法

cwd()

process.cwd() 返回运行 Node 的工作目录(绝对路径),比如在目录 /Users/huangtengfei/abc 下执行 node server.js,那么 process.cwd() 返回的就是 /Users/huangtengfei/abc。

另一个常用的获取路径的方法是 __dirname,它返回的是执行文件时该文件在文件系统中所在的目录。注意 process.cwd() 和 __dirname 的不同,前者是进程发起时的位置,后者是脚本的位置,两者可能不一致。

on()

process 对象部署了 EventEmitter 接口,可以使用 process.on() 方法监听各种事件,并指定回调函数。比如监听到系统发出进程终止信号时关闭服务器然后退出进程:


process.on('SIGTERM', function () {
 server.close(function () {
 process.exit(0);
 });
});

exit()

process.exit() 会让 Node 立即终止当前进程(同步),参数为一个退出状态码,0 表示成功,大于 0 的任意整数表示失败。

kill()

process.kill() 用来对特定 id 的进程(process.pid)发送信号,默认为 SIGINT 信号。比如杀死当前进程:


process.kill(process.pid, 'SIGTERM');

虽然名字叫 kill ,但其实 process.kill() 只是负责发送信号,具体发送完信号之后这个怎么处理这个指定进程,取决于信号种类和接收到这个信号之后做了什么操作(比如 process.exit() 或者只是 console.log('Ignored this single'))。

Child Process 模块

child_process 模块用于创建和控制子进程,其中最核心的是 .spawn() ,其他 API 算是针对特定场景对它的封装。使用前要先 require 进来:


const cp = require('child_process');

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

exec() 方法用于执行 shell 命令,它的第一个参数是字符串形式的命令,第二个参数(可选)用来指定子进程运行时的定制化操作,第三个参数(可选)用来设置执行完命令的回调函数。比如在一个特定目录 /Users/huangtengfei/abc 下执行 ls -l 命令:


cp.exec('ls -l', {
 cwd: '/Users/huangtengfei/abc'
}, (error, stdout, stderr) => {
 if (error) {
 console.error(`exec error: ${error}`);
 return;
 }
 console.log(`stdout: ${stdout}`);
 console.log(`stderr: ${stderr}`);
})

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

spawn() 用来创建一个子进程执行特定命令,与 exec() 的区别是它没有回调函数,只能通过监听事件来获取运行结果,它适用于子进程长时间运行的情况,可以实时输出结果。


const ls = cp.spawn('ls', ['-l']);

ls.stdout.on('data', (data) => {
 console.log(`stdout: ${data}`);
});

ls.stderr.on('data', (data) => {
 console.log(`stderr: ${data}`);
});

ls.on('close', (code) => {
 console.log(`child process exited with code $[code]`);
});

使用 spawn 可以实现一个简单的守护进程,在工作进程不正常退出时重启工作进程:



function spawn(mainModule) {
 const worker = cp.spawn('node', [ mainModule ]);

 worker.on('exit', function (code) {
  if (code !== 0) {
   spawn(mainModule);
  }
 });
}

spawn('worker.js');

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

fork() 用来创建一个子进程执行 node 脚本,fork('./child.js') 相当于 spawn('node', ['./child.js']) , 区别在于 fork 会在父子进程之间建立一个通信管道(fork() 的返回值),用于进程间通信。对该通信管道对象可以监听 message 事件,用来获取子进程返回的信息,也可以向子进程发送信息。



const proc = cp.fork('./child.js');
proc.on('message', function(msg) {
 console.log(`parent got message: ${msg}`);
});
proc.send({ hello: 'world' });


process.on('message', function(msg) {
 console.log(`child got message: ${msg}`);
});
process.send({ foo: 'bar' });

Cluster 模块

Node.js 默认单进程执行,但这样就无法利用多核计算机的资源,cluster 模块的出现就是为了解决这个问题的。在开发服务器程序时,可以通过 cluster 创建一个主进程和多个 worker 进程,让每个 worker 进程运行在一个核上,统一通过主进程监听端口和分发请求。


const cluster = require('cluster');
const http = require('http');
const numCPUs = require('os').cpus().length;

if (cluster.isMaster) {
 console.log(`Master ${process.pid} is running`);

 // Fork workers.
 for (let i = 0; i < numCPUs; i++) {
 cluster.fork();
 }

 cluster.on('exit', (worker, code, signal) => {
 console.log(`worker ${worker.process.pid} died`);
 });
} else {
 // Workers can share any TCP connection
 // In this case it is an HTTP server
 http.createServer((req, res) => {
 res.writeHead(200);
 res.end('hello worldn');
 }).listen(8000);

 console.log(`Worker ${process.pid} started`);
}

常用属性和方法

isMaster/isWorker

cluster.isMaster 用来判断当前进程是否是主进程,cluster.isWorker 用来判断当前进程是否是工作进程,两者返回的都是布尔值。

workers

cluster.workers 是一个包含所有 worker 进程的对象,key 为 worker.id,value 为 worker 进程对象。


// 遍历所有 workers
function eachWorker(callback) {
 for (const id in cluster.workers) {
 callback(cluster.workers[id]);
 }
}
eachWorker((worker) => {
 worker.send('big announcement to all workers');
});

fork([env])

cluster.fork() 方法用来新建一个 worker 进程,默认上下文复制主进程,只有主进程可调用。

常用事件

listening

在工作进程调用 listen 方法后,会触发一个 listening 事件,这个事件可以被 cluster.on('listening') 监听。

比如每当一个 worker 进程连进来时,输出一条 log 信息:


cluster.on('listening', (worker, address) => {
 console.log(
 `A worker is now connected to ${address.address}:${address.port}`);
});

exit

在工作进程挂掉时,会触发一个 exit 事件,这个事件可以被 cluster.on('exit') 监听。

比如自动重启 worker:


cluster.on('exit', (worker, code, signal) => {
 console.log('worker %d died (%s). restarting...',
 worker.process.pid, signal || code);
 cluster.fork();
});

worker 对象

worker 对象是 cluster.fork() 的返回值,代表一个 worker 进程。

worker.id

worker.id 是当前 worker 的唯一标识,也是保存在 cluster.workers 中的 key 值。

worker.process

所有的 worker 进程都是通过 child_process.fork() 生成的,这个进程对象保存在 worker.process 中。

worker.send()

worker.send() 用在主进程给子进程发送消息,在子进程中,使用 process.on() 监听消息并使用 process.send() 发送消息。


if (cluster.isMaster) {
 const worker = cluster.fork();
 worker.send('hi there');
} else if (cluster.isWorker) {
 process.on('message', (msg) => {
 process.send(msg);
 });
}

总结

以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作能带来一定的帮助,如果有疑问大家可以留言交流,谢谢大家对编程网的支持。

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

深入理解Node.js中的进程管理

下载Word文档到电脑,方便收藏和打印~

下载Word文档

猜你喜欢

深入理解Node.js中的进程管理

前言 本文主要对 Node.js 中进程管理相关的东西做一个简单介绍,包括 process 对象、child_process 模块和cluster 模块,详细的 API 可以查看官方文档,下面来看看详细的介绍吧。 Process 对象 pr
2022-06-04

Node.js PM2 入门指南:轻松管理 Node.js 进程

,搞定多进程管理,告别繁琐的进程监控。 Node.js、PM2、进程管理、监控
Node.js PM2 入门指南:轻松管理 Node.js 进程
2024-02-12

深入理解Node.js的HTTP模块

前言 我们知道传统的HTPP服务器会由Aphche、Nginx、IIS之类的软件来担任,但是nodejs并不需要,nodejs提供了http模块,自身就可以用来构建服务器,而且http模块是由C++实现的,性能可靠。其中封装了一个高校的HT
2022-06-04

深入理解python多进程编程

1、python多进程编程背景 python中的多进程最大的好处就是充分利用多核cpu的资源,不像python中的多线程,受制于GIL的限制,从而只能进行cpu分配,在python的多进程中,适合于所有的场合,基本上能用多线程的,那么基本上
2022-06-04

Linux 深入理解进程权限

Linux 进程权限分析 在linux下,关于文件权限,大部分人接触比较多,也比较熟悉了解.但是对进程权限一般知之甚少。本文总结一下linux系统下进程权限问题和现象。 需要强调的是,本文是linux系统下讨论,因为linux和unix有很
2022-06-04

深入浅析Node的进程管理工具“pm2”

本篇文章给大家分享Node的进程管理工具“pm2”,聊聊为什么需要pm2、安装和使用pm2的方法,希望对大家有所帮助!
2023-05-14

Node.js中创建和管理外部进程详解

Node被设计用来高效的处理I/O操作,但是你应该知道,有些类型的程序并不适合这种模式。比如,如果你打算用Node处理一个CPU密集的任务,你可能会堵塞事件循环,并因此降低了程序的响应。替代办法是,把CPU密集的任务分配给一个单独的进程来处
2022-06-04

深入理解node.js之path模块

node之path模块//引用该模块 var path = require("path");1、路径解析,得到规范化的路径格式//对window系统,目录分隔为'', 对于UNIX系统,分隔符为'/',针对'..'返回上一级;/与\都被统一
2022-06-04

Node.js Serverless 中的事件处理:深入了解 EventEmitter

本文将深入探讨 Node.js Serverless 中的事件处理,重点介绍 EventEmitter 的使用及其优势,并通过演示代码展示如何利用 EventEmitter 实现事件处理。
Node.js Serverless 中的事件处理:深入了解 EventEmitter
2024-02-21

ASP.NET Core处理管道的深入理解

前言 在 ASP.NET Core 的管道处理部分,实现思想已经不是传统的面向对象模式,而是切换到了函数式编程模式。这导致代码的逻辑大大简化,但是,对于熟悉面向对象编程,而不是函数式编程思路的开发者来说,是一个比较大的挑战。 处理请求的函数
2022-06-07

Linux编程进阶:深入理解exit函数原理

exit 函数是 Linux 系统中用于终止进程的一个重要函数清理资源:在调用 exit 函数时,会自动关闭所有已打开的文件描述符,并释放进程占用的内存资源。这些操作有助于确保系统资源得到合理分配和回收。终止子进程:如果当前进程有子进程,e
Linux编程进阶:深入理解exit函数原理
2024-09-09

Node.js进程管理之子进程实例分析

这篇“Node.js进程管理之子进程实例分析”文章的知识点大部分人都不太理解,所以小编给大家总结了以下内容,内容详细,步骤清晰,具有一定的借鉴价值,希望大家阅读完这篇文章能有所收获,下面我们一起来看看这篇“Node.js进程管理之子进程实例
2023-07-02

编程热搜

目录