Node.js 是一种非常流行的开发工具,其卓越的性能与便捷的开发方式使得它在前端开发中得到了广泛应用。但是,当服务器面临高并发时,单进程的 Node.js 服务器可能无法承受高负载的请求,因此我们需要使用多进程模型来进行性能优化。
1. Clusters
在 Node.js 中,使用 Cluster 模块可以实现多进程,Cluster 模块让开发者利用多核 CPU 构建高性能的服务器。Cluster 模块会创建很多子进程来处理请求,并且每个子进程都独立运行,互相之间不会干扰。
使用 Cluster 的示例代码如下:
const cluster = require('cluster'); const http = require('http'); const numCPUs = require('os').cpus().length; if (cluster.isMaster) { // 主进程 console.log(`主进程 ${process.pid} 正在运行`); // Fork worker processes for (let i = 0; i < numCPUs; i++) { cluster.fork(); } cluster.on('exit', (worker, code, signal) => { console.log(`worker ${worker.process.pid} died`); }); } else { // 工作进程,启动 HTTP 服务器 http.createServer((req, res) => { res.writeHead(200); res.end('Hello, World!'); }).listen(8000); console.log(`工作进程 ${process.pid} 启动`); }
使用 isMaster
判断当前是主进程还是工作进程,主进程负责创建多个子进程,并监听子进程的 exit 事件,当某个子进程退出时,主进程可以重新创建一个新的子进程来处理请求。
需要注意的是,子进程和父进程是共享端口的,也就是说,绑定的端口、配置等等都是相同的,这也就可以方便的实现负载均衡。
2. 多进程模型
虽然 Cluster 模块已经为我们提供了便捷的多进程管理方式,但是如何设计多进程模型才能最大化提高服务器的性能呢?
我们可以使用 Node.js 中的负载均衡模块,例如 nginx
、haproxy
等来分发请求,不同的进程并行处理请求,将在事件循环中的等待阻塞变为串行处理请求的过程,提高系统的吞吐量。
示例代码:
const http = require('http'); const cluster = require('cluster'); const numCPUs = require('os').cpus().length; if (cluster.isMaster) { console.log(`主进程 ${process.pid} 正在运行`); for (let i = 0; i < numCPUs; i++) { cluster.fork(); } } else { // 启动 http 服务器,但只处理请求的一部分 http.createServer((req, res) => { if (/[a-m]/i.test(req.url)) { res.writeHead(200); res.end(`worker ${process.pid} handling request in partition A/B`); } else { res.writeHead(200); res.end(`worker ${process.pid} handling request in partition C/D`); } }).listen(8000); console.log(`工作进程 ${process.pid} 启动`); }
上述代码中,我们将请求拆分为 A/B 和 C/D 两个部分,不同的进程处理不同部分的请求,以此来实现负载均衡,提高系统性能。
3. 性能测试
为了进一步验证使用 Clusters 和多进程模型对性能的提升,我们可以进行性能测试。
在测试之前,我们可以使用 ab
命令进行基准测试:
ab -n 1000 -c 100 http://localhost:8000/
该命令会发送 1000 个请求,并发数为 100。
单进程模型下,ab
命令执行结果如下:
Concurrency Level: 100 Time taken for tests: 5.061 seconds Complete requests: 1000 Failed requests: 0 Total transferred: 139000 bytes HTML transferred: 12000 bytes Requests per second: 197.47 [#/sec] (mean) Time per request: 506.136 [ms] (mean) Time per request: 5.061 [ms] (mean, across all concurrent requests) Transfer rate: 26.74 [Kbytes/sec] received Connection Times (ms) min mean[+/-sd] median max Connect: 0 1 0.7 1 2 Processing: 295 489 64.3 491 566 Waiting: 295 488 64.5 491 565 Total: 295 490 64.2 492 566
多进程模型下,ab
命令执行结果如下:
Concurrency Level: 100 Time taken for tests: 2.613 seconds Complete requests: 1000 Failed requests: 0 Total transferred: 139000 bytes HTML transferred: 12000 bytes Requests per second: 382.65 [#/sec] (mean) Time per request: 261.303 [ms] (mean) Time per request: 2.613 [ms] (mean, across all concurrent requests) Transfer rate: 51.91 [Kbytes/sec] received Connection Times (ms) min mean[+/-sd] median max Connect: 0 1 0.4 1 2 Processing: 50 220 28.8 221 257 Waiting: 50 220 28.9 221 252 Total: 50 221 28.8 222 257
可以看出,使用多进程模型可以显著提高系统的性能,请求每秒的处理量从 197.47 提升到了 382.65,而且每个请求的处理时间也从 506.136ms 降低至了 261.303ms。
总结
多进程模型的最终目的就是为了提高 Node.js 服务器的性能,而对于不同的实际业务场景,要根据实际情况进行调整和优化。
在开发过程中,多进程模型是一种常用的性能优化方式,而使用 Cluster 和多进程模型可以方便地实现多个子进程的管理和负载均衡,从而大大提高了系统的性能和吞吐量。
来源:JavaScript中文网 ,转载请注明来源 本文地址:https://www.javascriptcn.com/post/6593f1f5eb4cecbf2d88e1e6