前言

本文主要对 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 可以实现一个简单的守护进程,在工作进程不正常退出时重启工作进程:
/* daemon.js */
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 事件,用来获取子进程返回的信息,也可以向子进程发送信息。
/* main.js */
const proc = cp.fork('./child.js');
proc.on('message', function(msg) {
console.log(`parent got message: ${msg}`);
});
proc.send({ hello: 'world' });
/* child.js */
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 world\n');
}).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);
});
}
总结
以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作能带来一定的帮助,如果有疑问大家可以留言交流,谢谢大家对的支持。
# nodejs
# 进程
# 进程管理
# 多进程
# Nodejs进程管理模块forever详解
# Nodejs极简入门教程(三):进程
# node.js使用cluster实现多进程
# Node.js中创建和管理外部进程详解
# 防止Node.js中错误导致进程阻塞的办法
# Node.js中防止错误导致的进程阻塞的方法
# Nodejs中解决cluster模块的多进程如何共享数据问题
# 的是
# 都是
# 创建一个
# 回调
# 第一个
# 设为
# 第二个
# 多核
# 可选
# 新建一个
# 返回值
# 是一个
# 发送消息
# 运行环境
# 多个
# 遍历
# 长时间
# 适用于
# 会在
# 而不
相关文章:
极客网站有哪些,DoNews、36氪、爱范儿、虎嗅、雷锋网、极客公园这些互联网媒体网站有什么差异?
建站之星伪静态规则如何设置?
定制建站哪家更专业可靠?推荐榜单揭晓
C#如何序列化对象为XML XmlSerializer用法
如何快速搭建支持数据库操作的智能建站平台?
建站之家VIP精选网站模板与SEO优化教程整合指南
香港服务器网站搭建教程-电商部署、配置优化与安全稳定指南
如何用好域名打造高点击率的自主建站?
哈尔滨网站建设策划,哈尔滨电工证查询网站?
c++怎么实现高并发下的无锁队列_c++ std::atomic原子变量与CAS操作【详解】
如何在建站主机中优化服务器配置?
建站之星IIS配置教程:代码生成技巧与站点搭建指南
建站之星备案是否影响网站上线时间?
C++时间戳转换成日期时间的步骤和示例代码
专业型网站制作公司有哪些,我设计专业的,谁给推荐几个设计师兼职类的网站?
网站app免费制作软件,能免费看各大网站视频的手机app?
小建面朝正北,A点实际方位是否存在偏差?
建站之星ASP如何实现CMS高效搭建与安全管理?
建站之星后台密码如何安全设置与找回?
深圳网站制作培训,深圳哪些招聘网站比较好?
海南网站制作公司有哪些,海口网是哪家的?
制作网站外包平台,自动化接单网站有哪些?
专业网站制作企业网站,如何制作一个企业网站,建设网站的基本步骤有哪些?
GML (Geography Markup Language)是什么,它如何用XML来表示地理空间信息?
济南专业网站制作公司,济南信息工程学校怎么样?
昆明高端网站制作公司,昆明公租房申请网上登录入口?
北京网站制作公司哪家好一点,北京租房网站有哪些?
官网网站制作腾讯审核要多久,联想路由器newifi官网
如何通过虚拟主机快速完成网站搭建?
如何通过虚拟主机快速搭建个人网站?
官网建站费用明细查询_企业建站套餐价格及收费标准指南
深圳企业网站制作设计,在深圳如何网上全流程注册公司?
c# 在ASP.NET Core中管理和取消后台任务
如何将凡科建站内容保存为本地文件?
武汉网站制作费用多少,在武汉武昌,建面100平方左右的房子,想装暖气片,费用大概是多少啊?
零服务器AI建站解决方案:快速部署与云端平台低成本实践
关于BootStrap modal 在IOS9中不能弹出的解决方法(IOS 9 bootstrap modal ios 9 noticework)
如何在云主机快速搭建网站站点?
建站主机空间推荐 高性价比配置与快速部署方案解析
如何用AWS免费套餐快速搭建高效网站?
宝塔新建站点为何无法访问?如何排查?
网站制作新手教程,新手建设一个网站需要注意些什么?
小型网站建站如何选择虚拟主机?
活动邀请函制作网站有哪些,活动邀请函文案?
如何在阿里云购买域名并搭建网站?
如何用PHP工具快速搭建高效网站?
商务网站制作工程师,从哪几个方面把握电子商务网站主页和页面的特色设计?
Python lxml的etree和ElementTree有什么区别
如何快速生成ASP一键建站模板并优化安全性?
公司网站制作需要多少钱,找人做公司网站需要多少钱?
*请认真填写需求信息,我们会在24小时内与您取得联系。