在单核 CPU 系统之上我们采用 单进程 + 单线程 的模式来开发。在多核 CPU 系统之上,可以通过 child_process.fork 开启多个进程(Node.js 在 v0.8 版本之后新增了Cluster 来实现多进程架构) ,即 多进程 + 单线程 模式。注意:开启多进程不是为了解决高并发,主要是解决了单进程模式下 Node.js CPU 利用率不足的情况,充分利用多核 CPU 的性能。
Node.js 中的进程
process 模块
Node.js 中的进程 Process 是一个全局对象,无需 require 直接使用,给我们提供了当前进程中的相关信息。官方文档提供了详细的说明,感兴趣的可以亲自实践下 Process 文档。
- process.env:环境变量,例如通过 process.env.NODE_ENV 获取不同环境项目配置信息
- process.nextTick:这个在谈及 Event Loop 时经常为会提到
- process.pid:获取当前进程id
- process.ppid:当前进程对应的父进程
- process.cwd():获取当前进程工作目录,
- process.platform:获取当前进程运行的操作系统平台
- process.uptime():当前进程已运行时间,例如:pm2 守护进程的 uptime 值
- 进程事件:process.on(‘uncaughtException’, cb) 捕获异常信息、process.on(‘exit’, cb)进程推出监听
- 三个标准流:process.stdout 标准输出、process.stdin 标准输入、process.stderr 标准错误输出
- process.title 指定进程名称,有的时候需要给进程指定一个名称
以上仅列举了部分常用到功能点,除了 Process 之外 Node.js 还提供了 child_process 模块用来对子进程进行操作,在下文 Nodejs进程创建会继续讲述。
Node.js 进程创建
进程创建有多种方式,本篇文章以child_process模块和cluster模块进行讲解。
child_process模块
child_process 是 Node.js 的内置模块,官网地址:
- child_process 官网地址:http://nodejs.cn/api/child_pr...
几个常用函数:
四种方式
- child_process.spawn():适用于返回大量数据,例如图像处理,二进制数据处理。
- child_process.exec():适用于小量数据,maxBuffer 默认值为 200 * 1024 超出这个默认值将会导致程序崩溃,数据量过大可采用 spawn。
- child_process.execFile():类似 child_process.exec(),区别是不能通过 shell 来执行,不支持像 I/O 重定向和文件查找这样的行为
- child_process.fork(): 衍生新的进程,进程之间是相互独立的,每个进程都有自己的 V8 实例、内存,系统资源是有限的,不建议衍生太多的子进程出来,通长根据系统 CPU 核心数设置。
CPU 核心数这里特别说明下,fork 确实可以开启多个进程,但是并不建议衍生出来太多的进程,cpu核心数的获取方式const cpus = require('os').cpus();,这里 cpus 返回一个对象数组,包含所安装的每个 CPU/内核的信息,二者总和的数组哦。假设主机装有两个cpu,每个cpu有4个核,那么总核数就是8。
fork开启子进程 Demo
fork开启子进程解决文章起初的计算耗时造成线程阻塞。
在进行 compute 计算时创建子进程,子进程计算完成通过 send 方法将结果发送给主进程,主进程通过 message 监听到信息后处理并退出。
- fork_app.js
- const http = require('http');
- const fork = require('child_process').fork;
-
- const server = http.createServer((req, res) => {
- if(req.url == '/compute'){
- const compute = fork('./fork_compute.js');
- compute.send('开启一个新的子进程');
-
- // 当一个子进程使用 process.send() 发送消息时会触发 'message' 事件
- compute.on('message', sum => {
- res.end(`Sum is ${sum}`);
- compute.kill();
- });
-
- // 子进程监听到一些错误消息退出
- compute.on('close', (code, signal) => {
- console.log(`收到close事件,子进程收到信号 ${signal} 而终止,退出码 ${code}`);
- compute.kill();
- })
- }else{
- res.end(`ok`);
- }
- });
- server.listen(3000, 127.0.0.1, () => {
- console.log(`server started at http://${127.0.0.1}:${3000}`);
- });
- fork_compute.js
(编辑:ASP站长网)
|