【Node.js从基础到高级运用】二十五、Node.js中Cluster的作用

2024-04-19 11:52

本文主要是介绍【Node.js从基础到高级运用】二十五、Node.js中Cluster的作用,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

引言

Node.js中的cluster模块允许您轻松创建共享服务器端口的子进程。这是一个核心模块,用于在Node.js应用程序中实现多进程架构,以充分利用多核CPU系统的计算能力。

cluster介绍

当您启动一个Node.js应用程序时,默认情况下它运行在单个进程中。对于多核CPU系统来说,这意味着您可能没有充分利用系统的全部潜力。通过使用cluster模块,您可以启动一个主进程(通常称为“master”或“主”进程),它可以分叉多个工作进程(“workers”或“工作进程”),每个工作进程都是应用程序的一个实例,运行在自己的进程中。

主进程不负责处理实际的工作负载,而是负责监控和管理工作进程。例如,它可以根据需要创建新的工作进程或替换已经崩溃的工作进程。这样,即使某个工作进程崩溃,整个应用程序也可以继续运行。

cluster模块的基本使用步骤如下:

  1. 引入cluster模块。
  2. 使用cluster.isMaster属性检查当前进程是否是主进程。
  3. 在主进程中,使用cluster.fork()方法创建工作进程。
  4. 设置必要的事件监听,以便于主进程可以响应工作进程的启动、退出等事件。
  5. 在工作进程中,编写实际处理客户端请求的代码。

使用cluster模块的好处包括:

  • 提高性能:通过在多个核心上并行运行,可以更有效地利用服务器的硬件资源。
  • 提高可靠性:如果一个工作进程崩溃,它可以被新的工作进程替换,而不会影响其他工作进程或主进程。
  • 负载分配:Node.js的cluster模块可以在工作进程之间自动分配连接,以实现负载均衡。

基础使用

使用 cluster 模块来创建一个能够处理多核 CPU 的服务器。

// 导入http和cluster模块
const http = require('http');
const cluster = require('cluster');
const numCPUs = require('os').cpus().length; // 获取CPU的核心数if (cluster.isMaster) {console.log(`主进程 ${process.pid} 正在运行`);// 衍生工作进程。for (let i = 0; i < numCPUs; i++) {cluster.fork();}cluster.on('exit', (worker, code, signal) => {console.log(`工作进程 ${worker.process.pid} 已退出`);});
} else {// 工作进程可以共享任何TCP连接。// 在本例中,它是一个HTTP服务器http.createServer((req, res) => {res.writeHead(200);res.end('Hello World!');}).listen(3000);console.log(`工作进程 ${process.pid} 已启动`);
}

代码解释:

  1. 引入模块: 引入 http, cluster, 和 os 模块。
  2. 主进程与工作进程逻辑: 使用 cluster.isMaster 来区分代码执行是在主进程还是工作进程中。
  3. 主进程逻辑:
    • 主进程负责打印当前进程的 PID,并根据 CPU 核心数衍生相应数量的工作进程。
    • 监听 exit 事件以打印退出的工作进程信息。
  4. 工作进程逻辑:
    • 每个工作进程都设置了一个 HTTP 服务器监听同一个端口(3000端口)。
    • 工作进程的启动会被记录在日志中。

使用这种方法,Node.js 应用可以有效地利用多核 CPU,提高应用的处理能力和响应速度。

进阶使用:零停机重启

const http = require("http");
const cluster = require("cluster");
const os = require("os");//cpu数量(几核)
const cpus = os.cpus().length;
// console.log(`Clustering to ${cpus} CPUS`);
var express = require("express")();
//主进程
if (cluster.isMaster) {console.log("master process id :", process.pid);for (let i = 0; i < cpus; i++) {//分派子进程cluster.fork();}//服务器收到这个消息,退出任务process.on("SIGINT", function () {console.log("ctrl+c");process.exit();});express.listen(9000);// 当主进程收到指定消息时(访问restart),开始“零停机重启”操作。express.get("/restart", function (req, res, next) {const workers = Object.keys(cluster.workers);// console.log('workers',workers)//重启函数function restart_worker(i) {if (i >= workers.length) return;//第i个工作进程var worker = cluster.workers[workers[i]];console.log(`Stoping worker:${worker.process.pid}`);//中断工作进程worker.disconnect();//工作进程退出时worker.on("exit", function () {//启动工作进程const new_worker = cluster.fork();//当新的工作进程,准备好,并开始监听新的连接时,迭代重启下一个工作子进程new_worker.on("listening", function () {restart_worker(i + 1);})});}//重启第一个工作进程restart_worker(0);res.end("restart ok");});} else {//子进程执行内容const pid = process.pid;http.createServer(function (req, res) {console.log(`Handing request from ${pid}`);res.end(`Hello from ${pid}\n`);}).listen(8000, function () {console.log(`Started ${pid}`);})}

代码解析:

集群主进程用express提供web服务;

集群子工作进程用http提供web服务;
当主进程收到指定消息时(访问restart路径),开始“零停机重启”操作。

实现重点是:停掉一个工作进程,并重启一个新的工作进程,当新的工作进程启动好,并进入监听状态时(即:可正常提供Web服务时),再重启下一个工作进程,直到全部重启完成。

执行效果:

在这里插入图片描述
为了更直观展示效果加入一行代码:

http.createServer(function (req, res) {console.log(`Handing request from ${pid}`);res.end(`Hello from ${pid}\n`);}).listen(8000, function () {console.log(`Started ${pid}`);console.log(`${pid} hello 7777777777777777777777`)})

此时先启动服务:

node test25

再次修改代码:

http.createServer(function (req, res) {console.log(`Handing request from ${pid}`);res.end(`Hello from ${pid}\n`);}).listen(8000, function () {console.log(`Started ${pid}`);console.log(`${pid} hello 8888888888888888888888`)})

通过网页打开http://localhost:9000/restart触发重启:
在这里插入图片描述
结果:
在这里插入图片描述

总结

需要注意的是,cluster模块并不是万能的。例如,在有状态的应用程序中,您可能需要考虑如何在工作进程之间共享状态。此外,如果您的应用程序主要受到I/O限制而不是CPU限制,那么增加更多的工作进程可能不会带来太大的性能提升。

参考

Nodejs教程63:零停机重启

这篇关于【Node.js从基础到高级运用】二十五、Node.js中Cluster的作用的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/917471

相关文章

python panda库从基础到高级操作分析

《pythonpanda库从基础到高级操作分析》本文介绍了Pandas库的核心功能,包括处理结构化数据的Series和DataFrame数据结构,数据读取、清洗、分组聚合、合并、时间序列分析及大数据... 目录1. Pandas 概述2. 基本操作:数据读取与查看3. 索引操作:精准定位数据4. Group

python运用requests模拟浏览器发送请求过程

《python运用requests模拟浏览器发送请求过程》模拟浏览器请求可选用requests处理静态内容,selenium应对动态页面,playwright支持高级自动化,设置代理和超时参数,根据需... 目录使用requests库模拟浏览器请求使用selenium自动化浏览器操作使用playwright

C++中detach的作用、使用场景及注意事项

《C++中detach的作用、使用场景及注意事项》关于C++中的detach,它主要涉及多线程编程中的线程管理,理解detach的作用、使用场景以及注意事项,对于写出高效、安全的多线程程序至关重要,下... 目录一、什么是join()?它的作用是什么?类比一下:二、join()的作用总结三、join()怎么

Zabbix在MySQL性能监控方面的运用及最佳实践记录

《Zabbix在MySQL性能监控方面的运用及最佳实践记录》Zabbix通过自定义脚本和内置模板监控MySQL核心指标(连接、查询、资源、复制),支持自动发现多实例及告警通知,结合可视化仪表盘,可有效... 目录一、核心监控指标及配置1. 关键监控指标示例2. 配置方法二、自动发现与多实例管理1. 实践步骤

java中反射Reflection的4个作用详解

《java中反射Reflection的4个作用详解》反射Reflection是Java等编程语言中的一个重要特性,它允许程序在运行时进行自我检查和对内部成员(如字段、方法、类等)的操作,本文将详细介绍... 目录作用1、在运行时判断任意一个对象所属的类作用2、在运行时构造任意一个类的对象作用3、在运行时判断

Python中你不知道的gzip高级用法分享

《Python中你不知道的gzip高级用法分享》在当今大数据时代,数据存储和传输成本已成为每个开发者必须考虑的问题,Python内置的gzip模块提供了一种简单高效的解决方案,下面小编就来和大家详细讲... 目录前言:为什么数据压缩如此重要1. gzip 模块基础介绍2. 基本压缩与解压缩操作2.1 压缩文

python常用的正则表达式及作用

《python常用的正则表达式及作用》正则表达式是处理字符串的强大工具,Python通过re模块提供正则表达式支持,本文给大家介绍python常用的正则表达式及作用详解,感兴趣的朋友跟随小编一起看看吧... 目录python常用正则表达式及作用基本匹配模式常用正则表达式示例常用量词边界匹配分组和捕获常用re

Java中的for循环高级用法

《Java中的for循环高级用法》本文系统解析Java中传统、增强型for循环、StreamAPI及并行流的实现原理与性能差异,并通过大量代码示例展示实际开发中的最佳实践,感兴趣的朋友一起看看吧... 目录前言一、基础篇:传统for循环1.1 标准语法结构1.2 典型应用场景二、进阶篇:增强型for循环2.

Java 继承和多态的作用及好处

《Java继承和多态的作用及好处》文章讲解Java继承与多态的概念、语法及应用,继承通过extends复用父类成员,减少冗余;多态实现方法重写与向上转型,提升灵活性与代码复用性,动态绑定降低圈复杂度... 目录1. 继承1.1 什么是继承1.2 继承的作用和好处1.3 继承的语法1.4 子类访问父类里面的成

使用Python进行GRPC和Dubbo协议的高级测试

《使用Python进行GRPC和Dubbo协议的高级测试》GRPC(GoogleRemoteProcedureCall)是一种高性能、开源的远程过程调用(RPC)框架,Dubbo是一种高性能的分布式服... 目录01 GRPC测试安装gRPC编写.proto文件实现服务02 Dubbo测试1. 安装Dubb