简介
NodeJS的JavaScript运行在单个进程的单个线程上,一个JavaScript执行进程只能利用一个CPU核心,而如今大多数CPU均为多核CPU,为了充分利用CPU资源,Node提供了child_process和cluster模块来实现多进程以及进程管理。
child_process
child_process创建子进程的方法有如下四个
- spawn():启动一个子进程来执行命令
- exec():启动一个子进程来执行命令,并且通过回调函数通知子进程状况
- execFile():启动一个子进程来执行可执行文件
- fork():是 spawn() 的一个特例,创建子进程只需要指定要执行的 javascript 文件模块即可,子进程返回一个 child_process 对象,并附加父子进程间的通信渠道
- exec() 与 execFile() 创建时可以指定 timeout 属性设置超时时间,一旦创建的进程运行超过设定的时间将会被杀死
开始
这里使用fork()方法来创建子进程,fork()方法只需指定要执行的JavaScript文件模块,即可创建Node子进程
//master.js const childProcess = require('child_process') const cpuNum = require('os').cpus().length for (let i = 0; i < cpuNum; ++i) { childProcess.fork('./worker.js') } console.log('Master: Hello world.') //worker.js console.log('Worker-' + process.pid + ': Hello world.')
父子进程通信
通信的方法主要有以下两个
- on('message') --接收
- send() --发送
//master.js const childProcess = require('child_process') const worker = childProcess.fork('./worker.js') worker.send('你好 worker') worker.on('message',msg=>{ console.log(`我收到了来自子进程的消息:${msg}`) }) //worker.js process.on('message', msg => { console.log(`我收到了来自master的消息:${msg}`) process.send('你好 master') })
处理HTTP服务
//master.js const { createServer } = require('net') const childProcess = require('child_process') const cpuNum = require('os').cpus().length let workers = [] for (let i = 0; i < cpuNum; ++i) { workers.push(childProcess.fork('./worker.js')) console.log('Create worker-' + workers[i].pid) } //创建tcp服务器 const server = createServer() server.listen(8888, () => { console.log(`server listen 8888`) for (let i = 0; i < cpuNum; ++i) { workers[i].send('server', server) } // 关闭主线程服务器的端口监听 server.close() }) //worker.js const http = require('http') const httpServer = http.createServer((req, res) => { // 利用setTimeout模拟处理请求时的操作耗时 setTimeout(() => { res.writeHead(200, { 'Content-Type': 'text/plain' }) res.end('Request handled by worker-' + process.pid) }, 10) }) process.on('message', (msg, server) => { if (msg === 'server' && server) { server.on('connection', (socket) => { // 提交给HTTP服务器处理 httpServer.emit('connection', socket) }) } })
cluster
Node提供了cluster模块,该模块提供了更完善的API,除了能够实现多进程充分利用CPU资源以外,还能够帮助我们更好地进行进程管理和处理进程的健壮性问题。
const cluster = require('cluster') const express = require('express') const app = express() if (cluster.isMaster) { const cpuNum = require('os').cpus().length for (let i = 0; i < cpuNum; ++i) { cluster.fork() } // 创建进程完成后输出提示信息 cluster.on('online', (worker) => { console.log('Create worker-' + worker.process.pid) }) // 子进程退出后重启 cluster.on('exit', (worker, code, signal) => { console.log('[Master] worker ' + worker.process.pid + ' died with code: ' + code + ', and signal: ' + signal) cluster.fork() }) } else { app.get('/', (req, res) => { res.end(`worker:${process.pid}`) }) app.listen(8888, () => { console.log(`app listen 8888`) }) }
测试脚本
//client.js var request = require('request'); var mock = function () { request({ url: 'http://127.0.0.1:8888', method: "get", }, function (error, response, body) { if (!error && response.statusCode == 200) { console.log(response.body) } }); } for (let index = 0; index < 10; index++) { mock() }
pm2
https://blog.nowcoder.net/n/b9c44257e37c4f0ea67966dcf105ca96