简介
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

京公网安备 11010502036488号