在前端开发中,我们经常会使用 PM2 来管理我们的 Node.js 应用程序。在生产环境中,为了保证应用的高可用,我们通常会使用 PM2 自带的集群模式,来将多个进程分布在不同的 CPU 中运行。然而,在启动进程时,由于每个 Node.js 进程都需要加载 Node.js 运行时环境并执行初始化工作,因此启动耗时会较长。本文将介绍一些优化方案,以减少在 PM2 集群模式下启动 Node.js 进程的时间。
1. 环境搭建
在进行优化前,我们需要准备一些环境,以便测试我们的优化方案。本文中将使用以下环境:
- 操作系统:Ubuntu 20.04.2 LTS
- Node.js 版本:v14.16.1
- PM2 版本:v5.1.1
首先,我们需要搭建一个简单的 Node.js 应用程序,以便测试启动时间。在项目根目录下创建文件 app.js,内容如下:
-- -------------------- ---- ------- ----- ------- - ------------------- ----- --- - ---------- ------------ ----- ---- -- - --------------- --------- --- ---------------- -- -- - -------------------- --- --------- -- ---- -------- --- -- -- - ---------- ------------- -- - ----------------- -------- -- ------
在终端中进入项目根目录,使用以下命令启动应用程序:
$ node app.js
我们将看到服务器在启动 5 秒钟后输出 “Init done!”。
接下来,我们将使用 PM2 命令启动该应用程序。在终端中执行以下命令安装 PM2:
$ npm install -g pm2
安装完成后,使用以下命令启动 PM2:
$ pm2 start app.js
该命令会启动一个 Node.js 进程,并将其加入 PM2 的进程管理列表中。使用以下命令查看 PM2 中运行的应用程序:
$ pm2 list
我们将看到应用程序正在运行:
┌──────┬──────────┬─────────┬─────┬───────────┬──────────┐ │ Name │ mode │ status │ cpu │ memory │ uptime │ ├──────┼──────────┼─────────┼─────┼───────────┼──────────┤ │ app │ fork │ online │ 0% │ 10.4 MB │ 1s │ └──────┴──────────┴─────────┴─────┴───────────┴──────────┘
现在,我们已经准备好了测试环境。我们可以尝试一下在 PM2 集群模式下启动多个 Node.js 进程需要多长时间。
在终端中执行以下命令启动 PM2 集群模式下运行应用程序的 2 个进程:
$ pm2 start app.js -i 2
使用以下命令查看 PM2 中运行的应用程序:
$ pm2 list
我们将看到两个应用程序正在运行:
┌──────┬──────────┬─────────┬─────┬───────────┬──────────┐ │ Name │ mode │ status │ cpu │ memory │ uptime │ ├──────┼──────────┼─────────┼─────┼───────────┼──────────┤ │ app │ cluster │ online │ 0% │ 30.8 MB │ 1s │ │ app │ cluster │ online │ 0% │ 30.5 MB │ 1s │ └──────┴──────────┴─────────┴─────┴───────────┴──────────┘
我们会看到每个进程都需要启动 5 秒钟。
2. 优化方案
在 PM2 集群模式下启动多个 Node.js 进程需要启动很多个 Node.js 运行时环境,因此启动耗时较长。为了优化 PM2 集群模式下的进程启动时间,我们可以尝试使用以下方案:
2.1. 使用进程守护来缓存 Node.js 运行时环境
使用 PM2 中的进程守护功能,可以在运行 Node.js 进程的同时,也运行一个本地缓存的 Node.js 运行时环境。这样,在启动新的 Node.js 进程时,不需要每次重新加载 Node.js 运行时环境,可以通过加载本地缓存改善启动时间。
在终端中执行以下命令启动带有进程守护的 PM2:
$ pm2 start app.js -i 2 --watch --ignore-watch="node_modules"
该命令将启动一个 PM2 进程守护,并加上 --watch
参数来监测文件变化, --ignore-watch="node_modules"
参数来忽略 node_modules 目录下文件的变化。我们可以在终端中使用以下命令关闭 PM2 进程守护:
$ pm2 stop pm2 God
如果您需要重新启动该服务,可以使用以下命令:
$ pm2 start pm2 God
我们可以通过在 PM2 中使用 show <name>
命令来查看应用程序、守护进程和缓存进程的详细信息。以下是我们上述命令创建的缓存进程的输出:
┌──────┬─────────────┬─────────────┬───────┬───────────┐ │ Name │ status │ restarts │ uptime │ memory │ ├──────┼─────────────┼─────────────┼───────┼───────────┤ │ God │ online │ 0 │ 0s │ 13.6 MB │ └──────┴─────────────┴─────────────┴───────┴───────────┘
2.2. 使用 PM2 2.5 版本新增的 cluster_mode 参数
在 PM2 2.5 版本中,新增了 cluster_mode
参数,该参数可以在启动进程时直接将多个进程分布在不同的 CPU 上。这种方式可以显著降低进程启动时间。
在终端中执行以下命令升级 PM2:
$ npm install -g pm2@latest
然后,使用以下命令启动应用程序:
$ pm2 start app.js --instances 2 --exec node --cluster-mode
该命令会启动一个进程集群,其中包含 2 个进程。我们可以通过 --exec node
参数来指定要执行的命令。在这种模式下,PM2 会自动将进程分布在不同的 CPU 核心上。
我们可以在终端中使用以下命令观察启动的进程:
$ pm2 monit
下面是多进程启动的输出示例:
│ App name │ id │ mode │ pid │ status │ restart │ uptime │ cpu │ mem │ ├──────────┼────┼──────┼───────┼───────────┼────────┼───────────────────┼─────┼──────────┤ │ app │ 0 │ fork │ 10975 │ online │ 0 │ 0s │ 0% │ 5.2 MB │ │ app │ 1 │ fork │ 10976 │ online │ 0 │ 0s │ 0% │ 5.1 MB │
3. 总结
我们介绍了两种优化 PM2 集群模式下进程启动时间的方案:使用进程守护来缓存 Node.js 运行时环境和使用 PM2 2.5 版本新增的 cluster_mode 参数。这两种方案都可以有效地缩短启动时间,提高生产环境的稳定性和性能。
来源:JavaScript中文网 ,转载请注明来源 https://www.javascriptcn.com/post/651bd42d95b1f8cacd371085