如何使用集群扩展 Node.js 应用程序

作者选择了 女性工程师协会作为 写给捐赠计划的一部分接受捐赠。

介绍

当你在一个具有多个CPU的系统上运行一个 Node.js程序时,它会创建一个默认情况下只使用一个CPU来执行的过程.由于Node.js使用单个线程来执行你的JavaScript代码,该应用程序的所有请求都必须由该线程在单个CPU上处理。

作为解决方案,Node.js 引入了 cluster模块,该模块在同一台机器上创建了相同应用程序的多个副本,并使它们同时运行。 它还配备了负载平衡器,通过 round-robin 算法均匀分配过程之间的负载。

在本教程中,您将使用具有四个或多个CPU的机器上的集群模块扩展一个Node.js应用程序,您将创建一个不使用集群的应用程序,然后更改应用程序以使用集群。

前提条件

要遵循本教程,您将需要以下内容:

  • 具有四个或更多CPU的系统
  • 如果您正在使用 Ubuntu 22.04 的远程服务器,您可以通过遵循我们的 初始服务器设置来设置您的系统。

步骤 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:用于构建 Node.js 中的 Web 应用程序的框架
  • loadtest:一个负载测试工具,有助于生成流量来衡量应用程序的性能
  • pm2:一个自动将应用程序扩展到多个 CPU

运行以下命令来下载 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 则保持空闲:

A diagram showing a process running on one CPU of a machine with four CPUs, handling all the incoming requests

现在你没有使用集群模块来创建应用程序,你将使用集群模块来扩展应用程序以使用多个CPU。

步骤 3 – 聚合应用程序

在此步骤中,您将添加集群模块来创建相同程序的多个实例,以处理更多负载并提高性能。

Screenshot of processes running on each CPU of a machine that has four CPUs sharing load

在此图表中,请求通过主流程的负载平衡器进行,然后使用圆形罗宾算法在流程之间分配请求。

在您的终端中,创建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模块。在后两行中,您将导入dirnamefileURLToPath,用于将__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上运行:

Screenshot of processes running on each CPU of a machine that has four CPUs sharing load

通过将集群添加到应用程序中,您可以比较使用集群模块和没有集群模块的模块的程序性能。

步骤 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└────┴────────────────────┴──────────┴──────┴───────────┴──────────┴──────────┘

要继续管理您的集群,您可以运行以下命令:

CommandDescription
pm2 start app_nameStarts the cluster
pm2 restart app_nameKills the cluster and starts it again
pm2 reload app_nameRestarts the cluster without downtime
pm2 stop app_nameStops the cluster
pm2 delete app_nameDeletes the cluster

您现在可以使用pm2模块和cluster模块来扩展您的应用程序。

结论

在本教程中,您使用集群模块扩展了您的应用程序。首先,您创建了一个不使用集群模块的程序,然后创建了一个使用集群模块扩展应用程序到您的机器上的多个CPU的程序。

要进一步推进,您可以访问 cluster 模块文档页面 了解更多关于该模块的信息。

如果你想继续使用pm2,你可以参阅 PM2 - Process Management的文档,你也可以尝试我们的教程使用pm2How 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 处理非同步的任务

Published At
Categories with 技术
comments powered by Disqus