介绍
Node.js 是一个开源的 JavaScript 运行环境,用于构建服务器侧和网络应用程序. 该平台运行在 Linux、MacOS、FreeBSD 和 Windows 上. Node.js 应用程序可以在命令行运行,但我们将专注于将其作为服务运行,以便在重新启动或故障时自动重新启动,并可以在生产环境中安全使用。
在本教程中,我们将涵盖在一台Ubuntu 16.04服务器上设置一个生产准备的Node.js环境,该服务器将运行由PM2管理的Node.js应用程序,并通过Nginx反向代理程序为用户提供安全访问。
前提条件
本指南假定您有以下内容:
- 一个 Ubuntu 16.04 服务器,配置了具有
sudo
特权的非root用户,如在 Ubuntu 16.04 初始服务器设置指南中所描述(https://andsky.com/tech/tutorials/initial-server-setup-with-ubuntu-16-04)。 - 一个域名指向您的服务器的公共 IP,如 How to Set Up a Host Name with DigitalOcean 。本教程将使用 example.com 在整个过程中。
- Nginx 安装,涵盖在 How To Install Nginx on Ubuntu 16.04]
- Nginx 配置与 SSL 使用 Let's Encrypt 证书。
当您完成前提条件后,您将有一个服务器,服务于默认的 Nginx 位置主页 https://example.com/。
让我们通过在您的服务器上安装 Node.js 运行时间来开始。
步骤 1 – 安装 Node.js
我们将使用 NodeSource包档案安装 Node.js 的最新 LTS 版本。
首先,您需要安装 NodeSource PPA 才能访问其内容. 请确保您位于您的主目录中,并使用‘curl’来获取 Node.js 16.x 档案的安装脚本:
1cd ~
2curl -sL https://deb.nodesource.com/setup_16.x -o nodesource_setup.sh
您可以使用nano
检查本脚本的内容(或您喜爱的文本编辑器):
1nano nodesource_setup.sh
然后在sudo
下运行脚本:
1sudo bash nodesource_setup.sh
PPA 将被添加到您的配置中,您的本地包缓存将自动更新。从 nodesource 运行安装脚本后,您可以以上面的方式安装 Node.js 包:
1sudo apt-get install nodejs
nodejs
包包含node
二进制和npm
,因此您不需要单独安装npm
。
1sudo apt-get install build-essential
Node.js 运行时间已安装,并准备运行应用程序. 让我们写一个 Node.js 应用程序。
步骤 2 — 创建 Node.js 应用程序
我们会写一个 Hello World 应用程序,该应用程序会返回任何 HTTP 请求的Hello World
,这是一个样本应用程序,可以帮助您设置 Node.js,您可以用自己的应用程序代替它 - 只需确保您修改您的应用程序以倾听适当的 IP 地址和端口。
世界代码
首先,创建并打开您的 Node.js 应用程序进行编辑. 对于本教程,我们将使用nano
来编辑名为hello.js
的样本应用程序:
1cd ~
2nano hello.js
如果您想要,您可以在两个位置更换突出的端口,‘8080’(请确保使用非管理员端口,即1024或更大):
1[label hello.js]
2#!/usr/bin/env nodejs
3var http = require('http');
4http.createServer(function (req, res) {
5 res.writeHead(200, {'Content-Type': 'text/plain'});
6 res.end('Hello World\n');
7}).listen(8080, 'localhost');
8console.log('Server running at http://localhost:8080/');
现在保存和退出。
此 Node.js 应用程序在指定地址(‘localhost’)和端口(‘8080’)上收听,并以‘200’ HTTP 成功代码返回Hello World
。
测试应用
要测试您的应用程序,请将hello.js
设置为使用chmod
进行执行:
1chmod +x ./hello.js
然后这样运行:
1./hello.js
1[secondary_label Output]
2Server running at http://localhost:8080/
<$>[注] 注: 以这种方式运行 Node.js 应用程序将阻止额外的命令,直到应用程序通过按压 Ctrl-C 被杀死。
要测试应用程序,请在您的服务器上打开另一个终端会话,并使用弯曲
连接到 localhost:
1curl http://localhost:8080
如果您看到以下输出,应用程序正在正常工作,并在正确的地址和端口上收听:
1[secondary_label Output]
2Hello World
如果您看不到正确的输出,请确保您的 Node.js 应用程序正在运行,并配置为听取正确的地址和端口。
一旦你确定它正在工作,转回到你的其他终端,并杀死Node.js应用程序(如果你还没有)通过按 Ctrl+C。
步骤三:安装PM2
现在我们将安装PM2,这是Node.js应用程序的流程管理器,PM2提供了管理和解除应用程序(作为服务在背景中运行应用程序)的简单方法。
我們將使用「npm」,即與 Node.js 一起安裝的 Node 模組的包管理器,在我們的伺服器上安裝 PM2。
1sudo npm install -g pm2
-g
选项告诉npm
安装模块 globally,以便它在整个系统中可用。
步骤 4 – 使用 PM2 管理应用程序
我们将讨论一些PM2的基本用途。
启动应用
您要做的第一件事是使用pm2 start
命令在背景中运行您的应用程序hello.js
:
1pm2 start hello.js
这还会将您的应用程序添加到 PM2 的流程列表中,该列表每次启动应用程序时都会输出:
1[secondary_label Output]
2[PM2] Spawning PM2 daemon with pm2_home=/home/sammy/.pm2
3[PM2] PM2 Successfully daemonized
4[PM2] Starting /home/sammy/hello.js in fork_mode (1 instance)
5[PM2] Done.
6┌─────┬──────────┬─────────────┬─────────┬─────────┬──────────┬────────┬──────┬───────────┬──────────┬──────────┬──────────┬──────────┐
7│ id │ name │ namespace │ version │ mode │ pid │ uptime │ ↺ │ status │ cpu │ mem │ user │ watching │
8├─────┼──────────┼─────────────┼─────────┼─────────┼──────────┼────────┼──────┼───────────┼──────────┼──────────┼──────────┼──────────┤
9│ 0 │ hello │ default │ N/A │ fork │ 13734 │ 0s │ 0 │ online │ 0% │ 25.0mb │ sammy │ disabled │
10└─────┴──────────┴─────────────┴─────────┴─────────┴──────────┴────────┴──────┴───────────┴──────────┴──────────┴──────────┴──────────┘
正如您所看到的,PM2 会自动分配一个 name(基于文件名,不含.js
扩展)和一个 PM2 id。
如果应用程序故障或死亡,在PM2下运行的应用程序将自动重新启动,但需要采取额外的步骤来让应用程序在系统启动(启动或重新启动)上启动。
启动
子命令生成并配置一个启动脚本,以便在服务器机器人上启动PM2及其管理流程:
1pm2 startup systemd
结果输出的最后一行将包含一个命令,您必须使用超级用户权限运行:
1[secondary_label Output]
2[PM2] Init System found: systemd
3[PM2] You have to run this command as root. Execute the following command:
4sudo env PATH=$PATH:/usr/bin /usr/lib/node_modules/pm2/bin/pm2 startup systemd -u sammy --hp /home/sammy
运行生成的命令(类似于上面的突出输出,但使用您的用户名而不是sammy
)以设置PM2开始启动(使用来自自己的输出的命令):
1sudo env PATH=$PATH:/usr/bin /usr/lib/node_modules/pm2/bin/pm2 startup systemd -u sammy --hp /home/sammy
这将创建一个 systemd unit,为您的启动用户运行pm2
。这个pm2
实例,反过来,运行hello.js
。
1systemctl status pm2-sammy
有关 systemd 的详细概述,请参阅 Systemd Essentials: Working with Services, Units, and the Journal。
其他 PM2 用途(可选)
PM2提供了许多子命令,允许您管理或搜索有关您的应用程序的信息。 请注意,运行pm2
没有任何论点会显示一个帮助页面,包括示例使用,该页面比本教程的本节更详细地涵盖了PM2的使用。
使用此命令停止应用程序(指定PM2应用程序名称
或id
):
1pm2 stop app_name_or_id
使用此命令重新啟動應用程式(指定 PM2「應用程式名稱」或「id」):
1pm2 restart app_name_or_id
目前由 PM2 管理的应用程序列表也可以通过列表
子命令查看:
1pm2 list
有关特定应用程序的更多信息可以通过使用info
子命令找到(指定 PM2 App name 或 id):
1pm2 info example
PM2 流程监视器可以通过monit
子命令拉上,显示应用程序状态、CPU 和内存使用量:
1pm2 monit
现在您的 Node.js 应用程序正在运行,并由 PM2 管理,让我们设置反向代理。
步骤 5 — 将 Nginx 设置为反向代理服务器
现在你的应用程序正在运行,并听到 localhost,你需要为你的用户设置一种方式来访问它. 我们将为此目的设置 Nginx Web 服务器作为反向代理。
在前提教程中,我们将我们的 Nginx 配置设置为 /etc/nginx/sites-available/default
文件。
1sudo nano /etc/nginx/sites-available/default
在服务器
区块中,你应该有一个现有的位置/
区块,用以下配置来替换该区块的内容,如果你的应用程序设置为在不同的端口上聆听,请将突出部分更新到正确的端口号。
1[label /etc/nginx/sites-available/default]
2. . .
3 location / {
4 proxy_pass http://localhost:8080;
5 proxy_http_version 1.1;
6 proxy_set_header Upgrade $http_upgrade;
7 proxy_set_header Connection 'upgrade';
8 proxy_set_header Host $host;
9 proxy_cache_bypass $http_upgrade;
10 }
11}
假设我们的服务器在example.com
上可用,通过网页浏览器访问https://example.com/
将请求发送到hello.js
,在端口8080
听到localhost**
。
您可以将额外的位置
块添加到相同的服务器块中,以便提供在相同的服务器上其他应用程序的访问。例如,如果您也在端口8081
上运行另一个 Node.js 应用程序,您可以添加此位置块来允许通过http://example.com/app2
访问:
1[label /etc/nginx/sites-available/default — Optional]
2 location /app2 {
3 proxy_pass http://localhost:8081;
4 proxy_http_version 1.1;
5 proxy_set_header Upgrade $http_upgrade;
6 proxy_set_header Connection 'upgrade';
7 proxy_set_header Host $host;
8 proxy_cache_bypass $http_upgrade;
9 }
一旦您完成为您的应用程序添加位置块,保存和退出。
确保您没有输入任何语法错误,键入:
1sudo nginx -t
接下来,重新启动 Nginx:
1sudo systemctl restart nginx
假设您的 Node.js 应用程序正在运行,您的应用程序和 Nginx 配置是正确的,您现在应该能够通过 Nginx 反向代理程序访问您的应用程序。
结论
恭喜您! 您现在有 Node.js 应用程序在 Ubuntu 16.04 服务器上运行 Nginx 反向代理程序后面。 此反向代理程序设置足够灵活,可为用户提供您想要共享的其他应用程序或静态 Web 内容。