作者选择了 女性工程师协会作为 写给捐赠计划的一部分接受捐赠。
介绍
当你在一个具有多个CPU的系统上运行一个 Node.js程序时,它会创建一个默认情况下只使用一个CPU来执行的过程.由于Node.js使用单个线程来执行你的JavaScript代码,该应用程序的所有请求都必须由该线程在单个CPU上处理。
作为解决方案,Node.js 引入了 cluster
模块,该模块在同一台机器上创建了相同应用程序的多个副本,并使它们同时运行。 它还配备了负载平衡器,通过 round-robin 算法均匀分配过程之间的负载。
在本教程中,您将使用具有四个或多个CPU的机器上的集群
模块扩展一个Node.js应用程序,您将创建一个不使用集群的应用程序,然后更改应用程序以使用集群。
前提条件
要遵循本教程,您将需要以下内容:
- 具有四个或更多CPU的系统
- 如果您正在使用 Ubuntu 22.04 的远程服务器,您可以通过遵循我们的 初始服务器设置来设置您的系统。
- Node.js 在您的开发环境中设置。如果您正在运行 Ubuntu 22.04,请遵循 如何在 Ubuntu 22.04 上安装 Node.js 的选项 3。
步骤 1 - 设置项目目录
在此步骤中,您将创建该项目的目录,并下载您将在本教程中稍后构建的应用程序的依赖性。 在 步骤 2,您将使用 Express 构建该应用程序,然后在 步骤 3中将其扩展到内置的节点集群
模块的多个CPU,您将使用 步骤 4中的负载测试
包进行测量。
要开始,请创建一个目录,您可以将其称为cluster_demo
或您喜欢的任何目录名称:
1mkdir cluster_demo
接下来,进入目录:
1cd cluster_demo
然后,开始项目,这也将创建一个package.json
文件:
1npm init -y
y
选项告诉 NPM 接受所有默认选项。
当命令运行时,它将产生匹配以下的输出:
1[secondary_label Output]
2Wrote to /home/sammy/cluster_demo/package.json:
3
4{
5 "name": "cluster_demo",
6 "version": "1.0.0",
7 "description": "",
8 "main": "index.js",
9 "scripts": {
10 "test": "echo \"Error: no test specified\" && exit 1"
11 },
12 "keywords": [],
13 "author": "",
14 "license": "ISC"
15}
注意这些属性与您的特定项目相一致:
名称
: npm 包的名称版本
:您的包的版本号码main
:您的项目的入口点
要了解更多有关其他属性的信息,您可以查看 NPM 文档的 package.json
部分。
接下来,用您喜爱的编辑器打开package.json
文件(本教程将使用nano
):
1nano package.json
在您的「package.json」文件中,添加突出的文本,在导入包时启用支持 ES 模块:
1[label cluster_demo/package.json]
2{
3 ...
4 "author": "",
5 "license": "ISC",
6 "type": "module"
7}
保存并关闭文件以CTRL+X
。
接下来,您将下载以下软件包:
运行以下命令来下载 Express 包:
1npm install express
接下来,运行命令以下载全球的负载测试
和pm2
包:
1npm install -g loadtest pm2
现在你已经安装了必要的依赖性,你将创建一个不使用集群的应用程序。
步骤 2 — 创建应用程序而不使用集群
在此步骤中,您将创建一个包含单一路径的样本程序,该程序将在每个用户访问时启动一个 CPU 密集的任务. 该程序不会使用集群
模块,以便您可以访问在单个 CPU 上运行一个应用程序的单个实例的性能影响。
使用nano
或您最喜欢的文本编辑器,创建index.js
文件:
1nano index.js
在您的 index.js 文件中,添加以下行来导入和实例化 Express:
1[label cluster_demo/index.js]
2import express from "express";
3
4const port = 3000;
5const app = express();
6
7console.log(`worker pid=${process.pid}`);
在第一行中,您导入快递
包. 在第二行中,您将端口
变量设置为3000
端口,该端口将被应用程序服务器收听。
接下来,添加这些行来定义路径 /heavy
,该路径将包含一个CPU绑定的循环:
1[label cluster_demo/index.js]
2...
3app.get("/heavy", (req, res) => {
4 let total = 0;
5 for (let i = 0; i < 5_000_000; i++) {
6 total++;
7 }
8 res.send(`The result of the CPU intensive task is ${total}\n`);
9});
在/heavy
路径中,您定义了一个循环,将总
变量增加500万次,然后使用res.send()
方法发送含有总
变量值的响应,虽然CPU相关任务的示例是任意的,但它显示了CPU相关的任务而不添加复杂性。
接下来,调用Express模块的listen()
方法,以便在port
变量中存储在端口3000
上的聆听服务器:
1[label cluster_demo/index.js]
2...
3app.listen(port, () => {
4 console.log(`App listening on port ${port}`);
5});
完整的文件将匹配如下:
1[label cluster_demo/index.js]
2import express from "express";
3
4const port = 3000;
5const app = express();
6
7console.log(`worker pid=${process.pid}`);
8
9app.get("/heavy", (req, res) => {
10 let total = 0;
11 for (let i = 0; i < 5_000_000; i++) {
12 total++;
13 }
14 res.send(`The result of the CPU intensive task is ${total}\n`);
15});
16
17app.listen(port, () => {
18 console.log(`App listening on port ${port}`);
19});
当您完成添加代码后,保存并退出您的文件,然后使用节点
命令运行该文件:
1node index.js
当您运行命令时,输出将匹配如下:
1[secondary_label Output]
2worker pid=11023
3App listening on port 3000
输出表示正在运行的进程ID和一个确认服务器正在听到端口3000
的消息。
要测试应用程序是否工作,请打开另一个终端并运行以下命令:
1[environment second]
2curl http://localhost:3000/heavy
<$>[注] 注: 如果您正在远程服务器上遵循本教程,请打开另一个终端,然后输入以下命令:
1[environment second]
2ssh -L 3000:localhost:3000 your_non_root_user@your_server_ip
在连接时,输入以下命令以使用curl
向应用程序发送请求:
1[environment second]
2curl http://localhost:3000/heavy
美元
结果将匹配如下:
1[environment second]
2[secondary_label Output]
3The result of the CPU intensive task is 5000000
输出提供了CPU密集计算的结果。
在此时,您可以用CTRL+C
停止服务器。
当您使用节点
命令运行index.js
文件时,操作系统(OS)会创建一个进程。 一个进程是操作系统为运行程序所做的抽象。
二进制程序然后被放置并加载到分配给进程的内存中,从那里开始执行,当它运行时,它对系统中的其他进程没有意识,而且进程中发生的任何事情都不会影响其他进程。
由于您对 Node.js 应用程序的单个流程运行在具有多个 CPU 的服务器上,它将接收和处理所有传入请求. 在本图中,所有传入请求都被指向在单个 CPU 上运行的流程,而其他 CPU 则保持空闲:
现在你没有使用集群
模块来创建应用程序,你将使用集群
模块来扩展应用程序以使用多个CPU。
步骤 3 – 聚合应用程序
在此步骤中,您将添加集群
模块来创建相同程序的多个实例,以处理更多负载并提高性能。
在此图表中,请求通过主流程的负载平衡器进行,然后使用圆形罗宾算法在流程之间分配请求。
在您的终端中,创建primary.js
文件:
1nano primary.js
在primary.js
文件中,添加以下行来导入依赖:
1[label cluster_demo/primary.js]
2import cluster from "cluster";
3import os from "os";
4import { dirname } from "path";
5import { fileURLToPath } from "url";
6
7const __dirname = dirname(fileURLToPath(import.meta.url));
在前两行中,您将导入集群
和os
模块。在后两行中,您将导入dirname
和fileURLToPath
,用于将__dirname
变量值设置为index.js
文件正在执行的目录的绝对路径。这些导入是必要的,因为__dirname
在使用ES模块时没有定义,并且仅在 CommonJS 模块中默认定义。
接下来,添加以下代码来引用 index.js 文件:
1[label cluster_demo/primary.js]
2...
3const cpuCount = os.cpus().length;
4
5console.log(`The total number of CPUs is ${cpuCount}`);
6console.log(`Primary pid=${process.pid}`);
7cluster.setupPrimary({
8 exec: __dirname + "/index.js",
9});
首先,您将cpuCount
变量设置为您机器中的CPU数目,该数目应为四个或更高。接下来,您会记录控制台中的CPU数目。
接下来,您将使用cluster
模块的setupPrimary()
方法引用index.js
文件,以便在每个工人流程中执行。
接下来,添加以下代码来创建流程:
1[label cluster_demo/primary.js]
2...
3for (let i = 0; i < cpuCount; i++) {
4 cluster.fork();
5}
6cluster.on("exit", (worker, code, signal) => {
7 console.log(`worker ${worker.process.pid} has been killed`);
8 console.log("Starting another worker");
9 cluster.fork();
10});
循环在每个迭代过程中重复为cpuCount
中的值,并调用fork()
模块的fork()
方法。您使用on()
模块的on()
方法附加了exit
事件,以便在一个进程发出exit
事件时聆听,这通常是进程死亡时。
您的完整代码现在将匹配如下:
1[label cluster_demo/primary.js]
2import cluster from "cluster";
3import os from "os";
4import { dirname } from "path";
5import { fileURLToPath } from "url";
6
7const __dirname = dirname(fileURLToPath(import.meta.url));
8
9const cpuCount = os.cpus().length;
10
11console.log(`The total number of CPUs is ${cpuCount}`);
12console.log(`Primary pid=${process.pid}`);
13cluster.setupPrimary({
14 exec: __dirname + "/index.js",
15});
16
17for (let i = 0; i < cpuCount; i++) {
18 cluster.fork();
19}
20cluster.on("exit", (worker, code, signal) => {
21 console.log(`worker ${worker.process.pid} has been killed`);
22 console.log("Starting another worker");
23 cluster.fork();
24});
一旦你完成了添加行,保存和退出你的文件。
接下来,运行文件:
1node primary.js
输出将密切匹配如下(您的流程 ID 和信息的顺序可能有所不同):
1[secondary_label Output]
2The total number of CPUs is 4
3Primary pid=7341
4worker pid=7353
5worker pid=7354
6worker pid=7360
7App listening on port 3000
8App listening on port 3000
9App listening on port 3000
10worker pid=7352
11App listening on port 3000
输出将显示四个CPU,一个包括负载平衡器的主要流程,以及四个倾听3000
端口的工人流程。
接下来,回到第二个终端,然后将请求发送到‘/heavy’路线:
1curl http://localhost:3000/heavy
输出证实程序正在运作:
1[secondary_label Output]
2The result of the CPU intensive task is 5000000
您现在可以关闭服务器。
在此时刻,你将有四个流程在你的机器上的所有CPU上运行:
通过将集群添加到应用程序中,您可以比较使用集群
模块和没有集群
模块的模块的程序性能。
步骤 4 – 使用负载测试工具比较性能
在此步骤中,您将使用负载测试
包来生成对您所构建的两个程序的流量。您将比较使用集群
模块的primary.js
程序的性能,与不使用集群的index.js
程序的性能。
首先,您将测量index.js
文件的性能,该文件不使用cluster
模块,只在一个实例上运行。
在您的第一个终端中,运行index.js
文件来启动服务器:
1node index.js
您将收到一个输出,即应用程序正在运行:
1[secondary_label Output]
2worker pid=7731
3App listening on port 3000
接下来,回到您的第二台终端,使用负载测试
包向服务器发送请求:
1[environment second]
2loadtest -n 1200 -c 200 -k http://localhost:3000/heavy
-n
选项接受该包应该发送的请求数,即这里的请求数为 1200
。
一旦请求发送,包将返回类似于以下的输出:
1[environment second]
2[secondary_label Output]
3Requests: 0 (0%), requests per second: 0, mean latency: 0 ms
4Requests: 430 (36%), requests per second: 87, mean latency: 1815.1 ms
5Requests: 879 (73%), requests per second: 90, mean latency: 2230.5 ms
6
7Target URL: http://localhost:3000/heavy
8Max requests: 1200
9Concurrency level: 200
10Agent: keepalive
11
12Completed requests: 1200
13Total errors: 0
14Total time: 13.712728601 s
15Requests per second: 88
16Mean latency: 2085.1 ms
17
18Percentage of the requests served within a certain time
19 50% 2234 ms
20 90% 2340 ms
21 95% 2385 ms
22 99% 2406 ms
23 100% 2413 ms (longest request)
从这个输出中,请注意以下指标:
在此输出中,服务所有1200
请求花费了不到13秒
*每秒请求
衡量服务器每秒处理的请求数。
这些指标将取决于您的网络或处理器速度,但它们将接近这些例子。
现在你已经测量了 index.js 文件的性能,你可以停止服务器。
接下来,您将测量使用集群
模块的primary.js
文件的性能。
要做到这一点,回到第一个终端并重新启动primary.js
文件:
1node primary.js
您将收到与之前相同的信息的回复:
1[secondary_label Output]
2The total number of CPUs is 4
3Primary pid=7841
4worker pid=7852
5App listening on port 3000
6worker pid=7854
7App listening on port 3000
8worker pid=7853
9worker pid=7860
10App listening on port 3000
11App listening on port 3000
在第二个终端中,再次运行负载测试
命令:
1[environment second]
2loadtest -n 1200 -c 200 -k http://localhost:3000/heavy
当它完成时,您将收到类似的输出(根据系统上的CPU数量可能会有所不同):
1[environment second]
2[secondary_label Output]
3Requests: 0 (0%), requests per second: 0, mean latency: 0 ms
4
5Target URL: http://localhost:3000/heavy
6Max requests: 1200
7Concurrency level: 200
8Agent: keepalive
9
10Completed requests: 1200
11Total errors: 0
12Total time: 3.412741962 s
13Requests per second: 352
14Mean latency: 514.2 ms
15
16Percentage of the requests served within a certain time
17 50% 194 ms
18 90% 2521 ms
19 95% 2699 ms
20 99% 2710 ms
21 100% 2759 ms (longest request)
primary.js
应用程序的输出,该应用程序与cluster
模块一起运行,表示总时间从不使用集群的程序的13秒降至3秒。服务器每秒可处理的请求数量已从前面的88
增加到352
,这意味着您的服务器可以承担巨大的负载。
这个响应证实了扩展工作,你的应用程序可以在短时间内处理更多的请求,而不会有任何延迟. 如果你升级你的机器以获得更多的CPU,应用程序将自动扩展到CPU数量,并进一步提高性能。
作为提醒,您的终端输出中的指标将因您的网络和处理器速度而有所不同. 总时间和平均延迟将显著下降,总时间将迅速增加。
现在你已经进行了比较,并注意到应用程序在集群
模块上表现更好,你可以停止服务器。
步骤 5 — 使用pm2
来集群
到目前为止,您已经使用了群集
模块来根据机器上的CPU数量创建工人流程,您还增加了在死亡时重新启动工人流程的能力,在此步骤中,您将通过使用群集
模块构建的pm2
(LINK0)工人流程管理器来设置自动化扩展的替代方案。
要使用它,您需要运行pm2
包与您需要扩展的文件,这是本教程中的index.js
文件。
在您的初始终端中,使用以下命令启动pm2
集群:
1pm2 start index.js -i 0
-i
选项接受你想要创建 pm2
的工人流程的数量. 如果你通过了 0
参数, pm2
将自动创建尽可能多的工人流程,如机器上有 CPU。
在运行命令时,‘pm2’会向您显示有关工人流程的更多细节:
1[secondary_label Output]
2...
3[PM2] Spawning PM2 daemon with pm2_home=/home/sammy/.pm2
4[PM2] PM2 Successfully daemonized
5[PM2] Starting /home/sammy/cluster_demo/index.js in cluster_mode (0 instance)
6[PM2] Done.
7┌─────┬──────────┬─────────────┬─────────┬─────────┬──────────┬────────┬──────┬───────────┬──────────┬──────────┬──────────┬──────────┐
8│ id │ name │ namespace │ version │ mode │ pid │ uptime │ ↺ │ status │ cpu │ mem │ user │ watching │
9├─────┼──────────┼─────────────┼─────────┼─────────┼──────────┼────────┼──────┼───────────┼──────────┼──────────┼──────────┼──────────┤
10│ 0 │ index │ default │ 1.0.0 │ cluster │ 7932 │ 0s │ 0 │ online │ 0% │ 54.5mb │ nod… │ disabled │
11│ 1 │ index │ default │ 1.0.0 │ cluster │ 7939 │ 0s │ 0 │ online │ 0% │ 50.9mb │ nod… │ disabled │
12│ 2 │ index │ default │ 1.0.0 │ cluster │ 7946 │ 0s │ 0 │ online │ 0% │ 51.3mb │ nod… │ disabled │
13│ 3 │ index │ default │ 1.0.0 │ cluster │ 7953 │ 0s │ 0 │ online │ 0% │ 47.4mb │ nod… │ disabled │
14└─────┴──────────┴─────────────┴─────────┴─────────┴──────────┴────────┴──────┴───────────┴──────────┴──────────┴──────────┴──────────┘
表中包含每个工人的进程 ID、状态、CPU 利用率和内存消耗量,您可以使用这些数据来了解进程的行为。
当使用pm2
启动群集时,该包将在后台运行,即使在重新启动系统时也会自动重新启动。
如果您想从工人流程中读取日志,您可以使用以下命令:
1pm2 logs
您将收到日志的输出:
1[secondary_label Output]
2[TAILING] Tailing last 15 lines for [all] processes (change the value with --lines option)
3/home/sammy/.pm2/pm2.log last 15 lines:
4...
5PM2 | 2022-12-25T17:48:37: PM2 log: App [index:3] starting in -cluster mode-
6PM2 | 2022-12-25T17:48:37: PM2 log: App [index:3] online
7
8/home/sammy/.pm2/logs/index-error.log last 15 lines:
9/home/sammy/.pm2/logs/index-out.log last 15 lines:
100|index | worker pid=7932
110|index | App listening on port 3000
120|index | worker pid=7953
130|index | App listening on port 3000
140|index | worker pid=7946
150|index | worker pid=7939
160|index | App listening on port 3000
170|index | App listening on port 3000
在最后八行中,日志提供来自四个运行工人流程的输出,包括进程ID和端口号3000。
您还可以使用以下命令检查进程的状态:
1pm2 ls
结果将匹配下面的表:
1[secondary_label Output]
2┌─────┬──────────┬─────────────┬─────────┬─────────┬──────────┬────────┬──────┬───────────┬──────────┬──────────┬──────────┬──────────┐
3│ id │ name │ namespace │ version │ mode │ pid │ uptime │ ↺ │ status │ cpu │ mem │ user │ watching │
4├─────┼──────────┼─────────────┼─────────┼─────────┼──────────┼────────┼──────┼───────────┼──────────┼──────────┼──────────┼──────────┤
5│ 0 │ index │ default │ 1.0.0 │ cluster │ 7932 │ 5m │ 0 │ online │ 0% │ 56.6mb │ nod… │ disabled │
6│ 1 │ index │ default │ 1.0.0 │ cluster │ 7939 │ 5m │ 0 │ online │ 0% │ 55.7mb │ nod… │ disabled │
7│ 2 │ index │ default │ 1.0.0 │ cluster │ 7946 │ 5m │ 0 │ online │ 0% │ 56.5mb │ nod… │ disabled │
8│ 3 │ index │ default │ 1.0.0 │ cluster │ 7953 │ 5m │ 0 │ online │ 0% │ 55.9mb │ nod… │ disabled │
9└────┴────────────────────┴──────────┴──────┴───────────┴──────────┴──────────┘
现在集群正在运行,在同一个终端中输入以下命令来测试其性能:
1loadtest -n 1200 -c 200 -k http://localhost:3000/heavy
结果将密切匹配如下:
1[secondary_label Output]
2Requests: 0 (0%), requests per second: 0, mean latency: 0 ms
3
4Target URL: http://localhost:3000/heavy
5Max requests: 1200
6Concurrency level: 200
7Agent: keepalive
8
9Completed requests: 1200
10Total errors: 0
11Total time: 3.771868785 s
12Requests per second: 318
13Mean latency: 574.4 ms
14
15Percentage of the requests served within a certain time
16 50% 216 ms
17 90% 2859 ms
18 95% 3016 ms
19 99% 3028 ms
20 100% 3084 ms (longest request)
总时间
,每秒请求
和平均延迟
接近于您使用集群
模块时生成的指标。
为了改善您的工作流程,您可以生成一个配置文件来传输您的应用程序的配置设置. 这种方法将允许您在不传输选项的情况下启动或重新启动集群。
若要使用 config 文件,请删除当前集群:
1pm2 delete index.js
你会收到一个答案,它消失了:
1[secondary_label Output]
2[PM2] Applying action deleteProcessId on app [index.js](ids: [ 0, 1, 2, 3 ])
3[PM2] [index](2) ✓
4[PM2] [index](1) ✓
5[PM2] [index](0) ✓
6[PM2] [index](3) ✓
7┌────┬────────────────────┬──────────┬──────┬───────────┬──────────┬──────────┐
8│ id │ name │ mode │ ↺ │ status │ cpu │ memory │
9└────┴────────────────────┴──────────┴──────┴───────────┴──────────┴──────────┘
然后创建一个配置文件:
1pm2 ecosystem
输出将确认该文件已生成:
1[secondary_label Output]
2File /home/sammy/cluster_demo/ecosystem.config.js generated
重命名.js
为.cjs
以启用对 ES 模块的支持:
1mv ecosystem.config.js ecosystem.config.cjs
使用您的编辑器,打开配置文件:
1nano ecosystem.config.cjs
在你的ecosystem.config.cjs
文件中,添加下面的突出代码:
1[label cluster_demo/ecosystem.config.cjs]
2module.exports = {
3 apps : [{
4 script: 'index.js',
5 watch: '.',
6 name: "cluster_app",
7 instances: 0,
8 exec_mode: "cluster",
9 }, {
10 script: './service-worker/',
11 watch: ['./service-worker']
12 }],
13
14 deploy : {
15 production : {
16 user : 'SSH_USERNAME',
17 host : 'SSH_HOSTMACHINE',
18 ref : 'origin/master',
19 repo : 'GIT_REPOSITORY',
20 path : 'DESTINATION_PATH',
21 'pre-deploy-local': '',
22 'post-deploy' : 'npm install && pm2 reload ecosystem.config.cjs --env production',
23 'pre-setup': ''
24 }
25 }
26};
脚本
选项接受每个进程中将运行的文件,而pm2
包将生成。名称
属性接受任何可以识别集群的名称,如果您需要停止、重新启动或执行其他操作,这可以帮助。实例
属性接受您想要的实例数量。将实例
设置为0
将使pm2
生成尽可能多的进程,因为有CPU。exec_mode
接受cluster
选项,该选项告诉pm2
在集群中运行。
完成后,保存并关闭您的文件。
要启动集群,运行以下命令:
1pm2 start ecosystem.config.cjs
你会收到以下答案:
1[secondary_label Output]
2[PM2][WARN] Applications cluster_app, service-worker not running, starting...
3[PM2][ERROR] Error: Script not found: /home/node-user/cluster_demo/service-worker
4[PM2] App [cluster_app] launched (4 instances)
因为你没有在本教程中创建一个服务工
脚本,你可以忽略关于服务工
未找到的错误。
要确认集群正在运行,请检查状态:
1pm2 ls
您将收到一个答复,确认四个流程正在运行:
1[secondary_label Output]
2┌────┬────────────────────┬──────────┬──────┬───────────┬──────────┬──────────┐
3│ id │ name │ mode │ ↺ │ status │ cpu │ memory │
4├────┼────────────────────┼──────────┼──────┼───────────┼──────────┼──────────┤
5│ 0 │ cluster_app │ cluster │ 0 │ online │ 0% │ 56.9mb │
6│ 1 │ cluster_app │ cluster │ 0 │ online │ 0% │ 57.6mb │
7│ 2 │ cluster_app │ cluster │ 0 │ online │ 0% │ 55.9mb │
8│ 3 │ cluster_app │ cluster │ 0 │ online │ 0% │ 55.9mb │
9└────┴────────────────────┴──────────┴──────┴───────────┴──────────┴──────────┘
如果您想要重新启动集群,您可以使用您在ecosystem.config.cjs
文件中定义的应用名称,在这种情况下是cluster_app
:
1pm2 restart cluster_app
集群将重新启动:
1[secondary_label Output]
2Use --update-env to update environment variables
3[PM2] Applying action restartProcessId on app [cluster_app](ids: [ 0, 1, 2, 3 ])
4[PM2] [cluster_app](0) ✓
5[PM2] [cluster_app](1) ✓
6[PM2] [cluster_app](2) ✓
7[PM2] [cluster_app](3) ✓
8┌────┬────────────────────┬──────────┬──────┬───────────┬──────────┬──────────┐
9│ id │ name │ mode │ ↺ │ status │ cpu │ memory │
10├────┼────────────────────┼──────────┼──────┼───────────┼──────────┼──────────┤
11│ 0 │ cluster_app │ cluster │ 1 │ online │ 0% │ 48.0mb │
12│ 1 │ cluster_app │ cluster │ 1 │ online │ 0% │ 47.9mb │
13│ 2 │ cluster_app │ cluster │ 1 │ online │ 0% │ 38.8mb │
14│ 3 │ cluster_app │ cluster │ 1 │ online │ 0% │ 31.5mb │
15└────┴────────────────────┴──────────┴──────┴───────────┴──────────┴──────────┘
要继续管理您的集群,您可以运行以下命令:
Command | Description |
---|---|
pm2 start app_name | Starts the cluster |
pm2 restart app_name | Kills the cluster and starts it again |
pm2 reload app_name | Restarts the cluster without downtime |
pm2 stop app_name | Stops the cluster |
pm2 delete app_name | Deletes the cluster |
您现在可以使用pm2
模块和cluster
模块来扩展您的应用程序。
结论
在本教程中,您使用集群
模块扩展了您的应用程序。首先,您创建了一个不使用集群
模块的程序,然后创建了一个使用集群
模块扩展应用程序到您的机器上的多个CPU的程序。
要进一步推进,您可以访问 cluster
模块文档页面 了解更多关于该模块的信息。
如果你想继续使用pm2
,你可以参阅 PM2 - Process Management的文档,你也可以尝试我们的教程使用pm2
为How To Set Up a Node.js Application for Production on Ubuntu 22.04](https://andsky.com/tech/tutorials/how-to-set-up-a-node-js-application-for-production-on-ubuntu-22-04)
。
Node.js 还配备了 worker_threads
模块,允许您将 CPU 密集的任务分割到工人线程中,以便他们能够快速完成。 尝试我们关于 如何在 Node.js 中使用多线程的教程。 您还可以使用专用 Web 工人来优化前端的 CPU 相关任务,您可以通过遵循 如何与 Web 工人一起处理 CPU 密集的任务的教程来实现。 如果您想了解如何避免影响应用程序请求/响应周期的 CPU 相关任务,请参阅 如何使用 Node.js 和 BullMQ 处理非同步的任务。