【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:零停机重启

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/diannao/406.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【Python】什么是pip,conda,pycharm,jupyter notebook?conda基本教程

pip--conda--pycharm--jupyter notebook &#x1f343;pip&#x1f343;conda&#x1f343;Pycharm&#x1f343;jupyter notebook&#x1f343;Conda基本教程☘️进入base环境☘️创建一个新的环境☘️激活环境☘️退出环境☘️查看电脑上都安装了哪些环境☘️删除已创建的项目…

Mac 部署 GPT-2 预训练模型 gpt2-chinese-cluecorpussmall

文章目录 下载 GPT-2 模型快速开始 GPT-2 下载 GPT-2 模型 https://huggingface.co/uer/gpt2-chinese-cluecorpussmall git clone https://huggingface.co/uer/gpt2-chinese-cluecorpussmall # 或单独下载 LFS GIT_LFS_SKIP_SMUDGE1 git clone https://huggingface.co/uer/gpt…

使用Docker,【快速】搭建个人博客【WordPress】

目录 1.安装Mysql&#xff0c;创建&#xff08;WordPress&#xff09;用的数据库 1.1.安装 1.2.创建数据库 2.安装Docker 3.安装WodPress&#xff08;使用Docker&#xff09; 3.1.创建文件夹 3.2.查看镜像 3.3.获取镜像 3.4.查看我的镜像 3.5.使用下载的镜像&#xf…

Linux的学习之路:11、地址空间

摘要 本章主要是说一下地址空间&#xff0c;我也只是按照我的理解进行解释&#xff0c;可能说不清楚&#xff0c;欢迎指正 目录 摘要 一、空间布局图 二、代码测试一下 三、进程地址空间 四、测试代码 一、空间布局图 如下方图片可以看出地址空间有几种&#xff0c;这里…

Arduino源代码(ino)在Proteus中调试总结

一、前言 基于BluePill Plus开发板&#xff08;该板是毕设网红板&#xff09; BluePill Plus / WeAct Studio 微行工作室 出品 BluePill-Plus/README-zh.md at master WeActStudio/BluePill-Plus GitHub 首页-WeAct Studio-淘宝网 (taobao.com) 在Proteus中对应的例子是&…

每日OJ题_多源BFS①_力扣542. 01 矩阵(多源BFS解决最短路原理)

目录 多源BFS解决最短路算法原理 力扣542. 01 矩阵 解析代码 多源BFS解决最短路算法原理 什么是单源最短路 / 多源最短路&#xff1f; 之前的BFS解决最短路都是解决的单源最短路。 画图来说&#xff0c;单源最短路问题即为&#xff1a; 而对于多源最短路问题: 如何解决此…

Docker容器逃逸-特权模式-危险挂载-Procfs

Docker容器逃逸-特权模式-危险挂载 Docker这个概念&#xff1a; Docker 容器与虚拟机类似&#xff0c;但二者在原理上不同&#xff0c;容器是将操作系统层虚拟化&#xff0c;虚拟机则是虚拟化硬件&#xff0c;因此容器更具有便携性、高效地利用服务器。 ‍ Docker会遇到的安…

京东微服务microApp使用总结

前言 基于现有业务门户进行微服务基础平台搭建 主应用框架&#xff1a;vue3vite 子应用框架&#xff1a;vue2webpack / vue3vite在这里插入代码片 本地调试即可&#xff1a;主应用子应用进行打通&#xff08;注意&#xff1a;两者都是vue3vite&#xff09; 问题总结 1.嵌入…

压电式微机械超声换能器(PMUT)可替代传统超声换能器 下游应用范围广泛

压电式微机械超声换能器&#xff08;PMUT&#xff09;可替代传统超声换能器 下游应用范围广泛 压电式微机械超声换能器&#xff08;PMUT&#xff09;&#xff0c;是一种基于正逆压电效应与微机械&#xff08;MEMS&#xff09;技术制造而成的发射、接收超声波以实现检测的装置。…

个人开发 App 最简单方法:使用现代开发工具和平台

在移动应用市场的蓬勃发展下&#xff0c;个人开发者也有机会将自己的创意转化为实际的应用程序&#xff0c;并通过应用商店实现盈利。然而&#xff0c;对于许多初学者来说&#xff0c;如何开始个人开发一个应用可能会感到困惑。本文将介绍个人开发 App 的最简单方法&#xff0c…

Zynq7000系列中的IOP模块时钟使用

IOP模块的时钟&#xff08;用于内部控制器逻辑&#xff09;可以由时钟子系统生成&#xff0c;或者在某些情况下&#xff0c;由IOP的外部接口生成。在所有情况下&#xff0c;IOP的控制和状态寄存器都是由其AMBA接口时钟&#xff08;CPU_1x&#xff09;驱动的。有时&#xff0c;C…

ESA SNAP更新失败

snap用起来真是一言难尽&#xff0c;老师原话&#xff1a;很拉&#xff0c;不更新进行处理又会报错&#xff08;本科的时候就已经体验过了&#xff09;&#xff0c;但是更新又会发现老是失败&#xff0c;just pop up a window: try again later、unable to connect to update c…

️️️Vue3+Element-Plus二次封装一个可定制化的table组件

前言 为什么需要二次封装 开发后台管理系统,会接触到很多表格和表单,一但表格表单多起来,仅仅只需要一小部分改变&#xff0c;都需要在中重写一大堆代码,许多重复逻辑,我们可以把重复逻辑抽离出来二次封装一个组件 使用,减少在开发中需要编写的代码。 为什么需要定制化 每个…

前端请求404,后端保无此方法

1、微信小程序前端路径404 2、后端报无此路径 3、查看路径下对应的方法 发现忘了在list方法前加GetMapping(“/list”)&#xff0c;加上即可

Eclipse 配置JDK版本,Eclipse Maven install 时使用的JDK版本

Eclipse配置JDK版本 Eclipse 配置JDK版本的地方&#xff1f; 在Eclipse中配置JDK版本的步骤如下&#xff1a; 打开Eclipse IDE。转到菜单栏并选择 “Window”&#xff08;窗口&#xff09;选项。在下拉菜单中选择 “Preferences”&#xff08;首选项&#xff09;&#xff0c;或…

【pyhon】while语句的题目

1.计算1至100的偶数之和 sum_even 0 # 初始化偶数之和为0 i 1 # 从1开始循环 while i < 100: # 当i小于或等于100时&#xff0c;继续循环 if i % 2 0: # 如果i是偶数 sum_even i # 将i加到偶数之和上 i 1 # i自增1 print(“1至100的偶数之和为:”, sum_even) 给出乘…

计算机网络练习-计算机网络体系结构与参考模型

计算机网络分层结构 ----------------------------------------------------------------------------------------------------------------------------- 1.在ISO/OSI参考模型中&#xff0c;实现两个相邻结点间流量控制功能的是( )。 A.物理层 B. 数据链路层 C.网络层 D.传…

计算机网络—TCP协议详解:协议构成、深度解析(2)

&#x1f3ac;慕斯主页&#xff1a;修仙—别有洞天 ♈️今日夜电波&#xff1a;マリンブルーの庭園—ずっと真夜中でいいのに。 0:34━━━━━━️&#x1f49f;──────── 3:34 &#x1f504; ◀️…

M系Mac关闭SIP

文章目录 M系Mac关闭SIP一&#xff1a;查看SIP状态二&#xff1a;关闭SIP步骤 M系Mac关闭SIP 一&#xff1a;查看SIP状态 1、使用终端 打开终端 输入csrutil status&#xff0c;回车 你会看到以下信息中的一个&#xff0c;指示SIP状态 已打开 System Integrity Protection s…

Qt/C++音视频开发70-无感切换通道/无缝切换播放视频/多通道流畅切换/不同视频打开无缝切换

一、前言 之前就写过这个方案&#xff0c;当时做的是ffmpeg内核版本&#xff0c;由于ffmpeg内核解析都是代码实现&#xff0c;所以无缝切换非常完美&#xff0c;看不到丝毫的中间切换过程&#xff0c;看起来就像是在一个通道画面中。其实这种切换只能说是取巧办法&#xff0c;…