Node 利用 cluster 模块 实现高并发处理
在默认情况下,Node.js是单线程的,意味着它一次只能处理一个请求。当一个请求被接收并开始处理时,Node.js会一直处理该请求,直到完成或者异步处理(如进行文件读写或网络请求等耗时操作)
NodeJS 进程 是基于单进程的,在处理高并发的时候 并不理想,如果解决:
- 使用 cluster 模块,cluster 可以帮助你创建 多个子进程,对于多核心服务器 可以做到充分的 CPU 资源利用,cluster 模块创建的 多个子进程 之间 同时共享同一个端口,但每一个子进程都有自己的 事件循环、内存 和 V8实例
- 误区 worder_threads 模块无法解决高并发问题,worder_threads 模块 可以创建一个 工作线程,但是不是进程,worder_threads 模块创建的 工作线程 依旧跟主进程在同一进程中,只是 worder_threads 可以单独去计算 复杂处理,不堵塞主进程
现有一个 node 服务接口 地址 http://127.0.0.1:8080/home/cannon,其实现的功能如下:
function testauto(req,res){
for (let i = 1e7; i > 0; i--) {}
console.log('1');
res.reply({ token:"1213" });
}
对其,使用autocannon 进行压力测试,10秒内为服务器发起200个并发连接,其目前的性能截图如下:
在10.04秒内发送了4,000个请求,读取了1.1 MB的数据。并且不存在错误响应
下边 使用 cluster 模块 对其 优化
环境:m2 芯片
cluster 模块
- 创建多进程并行处理
- 一个主进程 Master 多个 工作进程 Worker
- 内置负载均衡(轮询 分配任务
- 可以监听同一端口
- 可以监听错误处理和重启
- 需要处理共享状态和数据同步问题
- 进程之间通信开销会导致系统负载和延迟
- 资源消耗和限制
// app.js
// app.listen(process.env.NODE_SERVE, ()=>{ console.log(`服务开启 ${process.pid}`) })
module.exports = app
require("./utils/work")
创建 work.js
// work.js
require('dotenv').config();
const cluster = require('cluster');
const os = require('os');
const app = require('../app'); // 导入Express应用程序
if (cluster.isMaster) {
console.log(`Master ${process.pid} is running`);
// 获取系统的 CPU 核心数量
const numCPUs = os.cpus().length;
// 创建 CPU 核心数量一半的 工作进程
for (let i = 0; i < numCPUs / 2; i++) {
cluster.fork();
}
// 监听工作进程退出事件
cluster.on('exit', (worker, code, signal) => {
console.log(`Worker ${worker.process.pid} died with code ${code} and signal ${signal}`);
// 可以在此处重新启动一个工作进程,以确保始终有足够的工作进程在运行
// cluster.fork();
});
} else {
// 启动 Express 应用程序
app.listen(process.env.NODE_SERVE, ()=>{ console.log(`服务开启 ${process.pid}`) })
}
再次 使用autocannon 进行压力测试,10秒内为服务器发起200个并发连接,其目前的性能截图如下:
在10.03秒内发送了12,000个请求,读取了4.02 MB的数据。并且无错误响应
cluster 模块 在 占用CPU 核心数 一半时 测试结果:
- 吞吐量 3 倍
- 传输数据 4 倍
如果本篇文章观看次数较多,后续将更新,node多进程如何实现平滑重启