Rocky Linux 9生产环境:Node.js应用部署与优化指南

介绍

Node.js是一个用于构建服务器端和网络应用程序的开源JavaScript运行环境。该平台可在Linux、macOS、FreeBSD和Windows上运行。尽管您可以在命令行上运行Node.js应用程序,但本教程将专注于将它们作为服务运行。这意味着它们将在重启或失败时自动重新启动,并且在生产环境中安全可靠。

在本教程中,您将在Rocky Linux 9服务器上设置一个可投入生产的Node.js环境。该服务器将运行由PM2管理的Node.js应用程序,并通过Nginx反向代理为用户提供安全访问应用程序的方式。Nginx服务器将使用由Let’s Encrypt提供的免费证书提供HTTPS服务。

先决条件

在进行本指南之前,假设您具备以下条件:

当您完成所有先决条件后,您将在https://example.com/上拥有一个为您的域名提供默认占位页面的服务器。

第一步 — 创建一个Node.js应用程序

让我们编写一个“Hello World”应用程序,它会对任何HTTP请求返回“Hello World”。这个示例应用程序将帮助您开始使用Node.js。您可以将其替换为自己的应用程序,只需确保修改应用程序以侦听适当的IP地址和端口。

Rocky Linux 9自带的默认文本编辑器是vivi是一个非常强大的文本编辑器,但对于没有经验的用户来说,可能会有些复杂。您可能希望安装一个更用户友好的编辑器,比如nano,以便在您的Rocky Linux 9服务器上编辑配置文件。

sudo dnf install nano

现在,使用nano或您最喜欢的文本编辑器,创建一个名为hello.js的示例应用程序。

nano hello.js

将以下代码插入文件中:

// hello.js
const http = require('http');

const hostname = '127.0.0.1';
const port = 3000;

const server = http.createServer((req, res) => {
  res.statusCode = 200;
  res.setHeader('Content-Type', 'text/plain');
  res.end('Hello World\n');
});

server.listen(port, hostname, () => {
  console.log(`Server running at http://${hostname}:${port}/`);
});

这是文章《如何在Rocky Linux 9上为生产环境设置Node.js应用程序》的第2部分(共4部分)。

内容片段:

const http = require('http');

const hostname = 'localhost';
const port = 3000;

const server = http.createServer((req, res) => {
  res.statusCode = 200;
  res.setHeader('Content-Type', 'text/plain');
  res.end('Hello World!\n');
});

server.listen(port, hostname, () => {
  console.log(`Server running at http://${hostname}:${port}/`);
});

保存文件并退出编辑器。如果使用的是nano,请按下Ctrl+X,然后在提示时按下Y,最后按下Enter键。

这个Node.js应用程序监听指定的地址(本地主机)和端口(3000),并以200 HTTP成功代码返回“Hello World!”。由于我们在本地主机上监听,远程客户端无法连接到我们的应用程序。

要测试您的应用程序,请输入:

  1. node hello.js

 

您将会收到以下的输出结果。

输出
Server running at http://localhost:3000/

注意:以这种方式运行Node.js应用程序将阻塞其他命令,直到通过按下CTRL+C来终止应用程序。为了测试应用程序,请在您的服务器上打开另一个终端会话,并通过curl连接到本地主机。

  1. curl http://localhost:3000

 

如果您得到以下输出,则表示应用程序正常工作并正在正确的地址和端口上进行监听:

输出
Hello World!

如果您没有得到预期的输出,请确保您的Node.js应用程序正在运行并配置为在正确的地址和端口上侦听。

确认应用程序正常运行后,请按下CTRL+C键关闭应用程序(如果您还没有关闭的话)。

第二步 – 安装PM2

安装和配置PM2

这是文章《如何在Rocky Linux 9上为生产环境设置Node.js应用程序》的第3部分(共4部分)。

接下来,让我们安装PM2,这是一个用于Node.js应用程序的进程管理器。PM2可以将应用程序守护化,使其作为后台服务持续运行。

使用npm在你的服务器上安装最新版本的PM2。

  1. sudo npm install pm2@latest -g

-g 选项告诉npm在全局安装该模块,使其在整个系统范围内可用。

让我们首先使用 pm2 start 命令在后台运行你的应用程序 hello.js

  1. pm2 start hello.js

这也会将您的应用程序添加到PM2的进程列表中,每次启动应用程序时会输出该列表。

输出
... [PM2] Spawning PM2 daemon with pm2_home=/home/sammy/.pm2
[PM2] PM2 Successfully daemonized
[PM2] Starting /home/sammy/hello.js in fork_mode (1 instance)
[PM2] Done.
┌────┬────────────────────┬──────────┬──────┬───────────┬──────────┬──────────┐
│ id │ name               │ mode     │ ↺    │ status    │ cpu      │ memory   │
├────┼────────────────────┼──────────┼──────┼───────────┼──────────┼──────────┤
│ 0  │ hello              │ fork     │ 0    │ online    │ 0%       │ 25.2mb   │
└────┴────────────────────┴──────────┴──────┴───────────┴──────────┴──────────┘

如上所示,PM2会自动分配一个应用程序名称(基于文件名,不包括 .js 扩展名)和一个PM2 ID。PM2还会维护其他信息,例如进程的PID、当前状态以及内存使用情况。

如果应用程序在PM2下运行,即使应用程序崩溃或被终止,它也会自动重新启动。但是,我们可以采取额外的步骤,使用 startup 子命令来在系统启动时启动应用程序。这个命令会生成并配置一个启动脚本,以在服务器启动时启动PM2及其管理的进程。

  1. pm2 startup systemd
输出
... [PM2] To setup the Startup Script, copy/paste the following command:
sudo env PATH=$PATH:/usr/bin /usr/local/lib/node_modules/pm2/bin/pm2 startup systemd -u sammy --hp /home/sammy

复制并运行提供的命令(这样可以避免以sudo方式运行Node.js工具时出现权限问题)。

  1. sudo env PATH=$PATH:/usr/bin /usr/local/lib/node_modules/pm2/bin/pm2 startup systemd -u sammy --hp /home/sammy
输出
... [ 'systemctl enable pm2-sammy' ]
[PM2] Writing init configuration in /etc/systemd/system/pm2-sammy.service
[PM2] Making script booting at startup...
[PM2] [-] Executing: systemctl enable pm2-sammy...
Created symlink /etc/systemd/system/multi-user.target.wants/pm2-sammy.service → /etc/systemd/system/pm2-sammy.service.
[PM2] [v] Command successfully executed.
+---------------------------------------+
[PM2] Freeze a process list on reboot via:
$ pm2 save
[PM2] Remove init script via:
$ pm2 unstartup systemd

现在,您需要对刚刚生成的系统服务进行编辑,以使其与Rocky Linux的SELinux安全系统兼容。使用nano或您喜欢的文本编辑器打开 /etc/systemd/system/pm2-sammy.service 文件。

  1. sudo nano /etc/systemd/system/pm2-sammy.service

在配置文件的 [Service] 块中,将 PIDFile 设置的内容替换为 /run/pm2.pid,并添加另一个高亮显示的 Environment 行。

这是文章《如何在Rocky Linux 9上为生产环境设置Node.js应用程序》的第4部分(共4部分)。

[Unit]
Description=PM2 进程管理器
Documentation=https://pm2.keymetrics.io/
After=network.target

[Service]
Type=forking
User=sammy
LimitNOFILE=infinity
LimitNPROC=infinity
LimitCORE=infinity
Environment=PATH=/home/sammy/.local/bin:/home/sammy/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/root/bin:/usr/bin:/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin
Environment=PM2_HOME=/home/sammy/.pm2
PIDFile=/run/pm2.pid
Restart=on-failure
Environment=PM2_PID_FILE_PATH=/run/pm2.pid

ExecStart=/usr/local/lib/node_modules/pm2/bin/pm2 resurrect
ExecReload=/usr/local/lib/node_modules/pm2/bin/pm2 reload all
ExecStop=/usr/local/lib/node_modules/pm2/bin/pm2 kill

[Install]

保存并关闭文件。您现在已经创建了一个在启动时为您的用户运行 PM2 的 Systemd 单元。这个 PM2 实例将运行 hello.js

使用 systemctl 启动服务。

  1. sudo systemctl start pm2-sammy

查看 Systemd 单元的状态。

  1. systemctl status pm2-sammy

要详细了解 Systemd,请查阅《Systemd Essentials: Working with Services, Units, and the Journal》。

除了我们已经涵盖的内容之外,PM2 还提供了许多子命令,可以让您管理或查询有关您的应用程序的信息。

使用该命令停止一个应用程序(请指定 PM2 应用的名称或 ID)。

  1. pm2 stop app_name_or_id

重启一个应用程序:

  1. pm2 restart app_name_or_id

列出当前由 PM2 管理的应用程序。

  1. pm2 list

使用应用名称获取有关特定应用程序的信息。

  1. pm2 info app_name

可以使用 monit 子命令调出 PM2 进程监视器。这将显示应用程序的状态、CPU 和内存使用情况。

  1. pm2 monit

请注意,运行 pm2 不带任何参数也会显示帮助页面及示例用法。

既然您的 Node.js 应用程序正在运行并由 PM2 管理,那么让我们设置反向代理。

第三步 – 将 Nginx 设置为反向代理服务器

您的应用正在本地运行和监听,但是您需要设置一种方式让用户访问它。我们将设置 Nginx 作为反向代理服务器来实现这个目的。

在先决教程中,您需要在 /etc/nginx/conf.d/your_domain.conf 文件中设置您的 Nginx 配置。打开这个文件进行编辑。

  1. sudo nano /etc/nginx/conf.d/your_domain.conf

在服务器块内部,您应该有一个现有的 location / 块。将该块的内容替换为以下配置。如果您的应用程序设置为侦听不同的端口,请将突出显示的部分更新为正确的端口号。

您的域名配置文件位于 /etc/nginx/conf.d/your_domain.conf

server {
...
    location / {
        proxy_pass http://localhost:3000;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection 'upgrade';
        proxy_set_header Host $host;
        proxy_cache_bypass $http_upgrade;
    }
...
}

这个配置使服务器能够在根目录下响应请求。假设我们的服务器在 your_domain 上可用,通过 Web 浏览器访问 https://your_domain/ 会将请求发送到位于本地主机监听端口 3000 的 hello.js

您可以在同一个服务器块中添加额外的 location 块,以便让其他应用程序在同一服务器上获得访问权限。例如,如果您还在 3001 端口上运行另一个 Node.js 应用程序,您可以添加这个 location 块来通过 https://您的域名/app2 访问它。

/etc/nginx/conf.d/your_domain.conf — 可选项

server {
...
    location /app2 {
        proxy_pass http://localhost:3001;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection 'upgrade';
        proxy_set_header Host $host;
        proxy_cache_bypass $http_upgrade;
    }
...
}

完成添加应用程序的 location 模块后,请保存文件并退出编辑器。

请确保您在编辑时没有引入任何语法错误。

  1. sudo nginx -t

重启 Nginx:

  1. sudo systemctl restart nginx

假设您的 Node.js 应用程序正在运行,且应用程序和 Nginx 的配置正确,您现在应该能够通过 Nginx 反向代理访问您的应用程序。尝试通过访问服务器的 URL(公共 IP 地址或域名)来验证。

结论

恭喜!您现在已经在一个 Rocky Linux 9 服务器上使用 Nginx 反向代理运行您的 Node.js 应用程序。这个反向代理设置足够灵活,可以让您的用户访问您想分享的其他应用程序或静态网络内容。

接下来,您可能想了解如何使用 Docker 构建 Node.js 应用程序。

bannerAds