如何使用Systemd和Nginx部署Node.js应用程序
介绍
将 Web 应用程序部署到 Droplet 时,可能很容易使用与开发中使用的相同类型的设置,即 通过在终端中运行“ruby app.rb”或“node server.js”来启动服务器。 这既简单又容易,同时提供可见的日志。 甚至可以使用“screen”或“tmux”或“nohup”让它在 SSH 会话被丢弃时继续运行。 这很危险:如果服务器崩溃并且周围没有人重新启动它会发生什么?
可以使用 forever 和 crontab 来解决这个问题。 本教程提供了一个更强大但更复杂的解决方案。 使用 systemd(Arch 和 Fedora 以及未来的 CentOS 可用),可以通过 cgroups 彻底管理 Web 应用程序:日志、正常运行时间、资源和安全性,高级守护程序启动可以所有这些都以统一的方式进行访问、控制和微调。
本教程使用一个简单的 Node.js 应用程序,但也适用于大多数(如果不是全部)其他应用程序(如 Ruby、Python 等)。 对于 PHP Web 应用程序,建议改用更专业的 LAMP 或 LEMP 堆栈。
将为 Fedora 和 Arch 提供命令,请留意哪些命令可以避免配置错误和/或混淆。 如果未指明,则两个系统的命令相同。 还建议您在逐步尝试之前通读整个教程,以便了解它的含义以及它是否适合您的情况。
系统预备
- 具有 systemd 的服务器。 Arch Linux 和 Fedora droplets 默认是这样配置的。
- Nginx,用作反向代理 http 和 websocket 服务器。
- Git,用于安装 nvm,如果使用 git,则拉取您的应用程序。
- Root 访问。 也可以以普通用户身份登录并 sudo 所有命令,或 su - 或 sudo su - 到 root 提示符。
安装包
拱:
# pacman -Sy # pacman -S nginx git
软呢帽:
# yum install nginx git
申请准备
这些是您可以根据自己的喜好自定义的设置,但必须在开始之前决定并设置它们。
用户
该应用程序将在其自己的单独用户帐户中运行。 选择一个名称,它应该与应用程序相关,以便于记忆和维护。 这里使用srv-node-sample
。
# useradd -mrU srv-node-sample
港口
为避免冲突,请选择高端口。 这里使用“15301”。
应用程序设置
首先安装应用程序运行所需的内容。 对于 Node.js(以及 Ruby、Python……),有两种选择:要么使用系统的运行时,要么使用特定于用户的安装(例如 使用 nvm、rbenv、RVM、virtualenv 等)。
使用系统节点
拱:
# pacman -S nodejs
软呢帽:
# yum install nodejs
使用特定于用户的安装
这必须安装在应用程序的主目录中,即 /home/srv-node-sample
,通过以该用户身份登录最容易完成:
# su srv-node-sample
$ cd $ curl https://raw.github.com/creationix/nvm/master/install.sh | sh $ source ~/.nvm/nvm.sh $ nvm install 0.10 $ nvm alias default 0.10
然后记下节点二进制文件的安装位置:
$ which node /home/srv-node-sample/.nvm/v0.10.22/bin/node
部署您的应用程序
登录到 srv-node-sample
后,部署您的代码。 这只是一个示例,您的过程会有所不同。
$ git clone git@server.company.tld:user/repo.git . $ npm install $ grunt deploy
对于本教程,使用以下示例应用程序:
js var http = require('http'); http.createServer(function(req, res) { res.end('<h1>Hello, world.</h1>'); }).listen(15301);
然后返回根目录:
$ exit
Nginx 设置
本教程仅简要介绍了必要的配置,有关配置 Nginx 的更全面的教程,请参阅 “如何配置 Nginx Web 服务器” 或 nginx 手册。
把它放在你的服务器块中:
location / { proxy_pass http://localhost:15301/; proxy_set_header Host $host; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; }
然后设置它的守护进程:
# systemctl enable nginx # systemctl restart nginx
系统设置
在 /etc/systemd/system/node-sample.service
中为应用程序创建一个服务文件。
有几个变量需要填写:
- [节点二进制] 这是作为 srv-node-sample 用户的“哪个节点”的输出。 上面提到的
/usr/bin/node
或~/.nvm/...
路径。 - [主文件] 这是您的应用程序的主文件。 在这里,“index.js”。
- 不要忘记替换
srv-node-sample
!
[Service] ExecStart=[node binary] /home/srv-node-sample/[main file] Restart=always StandardOutput=syslog StandardError=syslog SyslogIdentifier=node-sample User=srv-node-sample Group=srv-node-sample Environment=NODE_ENV=production [Install] WantedBy=multi-user.target
现在启动服务:
# systemctl enable node-sample # systemctl start node-sample
用法
地位
# systemctl status node-sample node-sample.service Loaded: loaded (/etc/systemd/system/node-sample.service; enabled) Active: active (running) since Fri 2013-11-22 01:12:15 UTC; 35s ago Main PID: 7213 (node) CGroup: name=systemd:/system/node-sample.service └─7213 /home/srv-node-sample/.nvm/v0.10.22/bin/node /home/srv-nod... Nov 22 01:12:15 d02 systemd[1]: Started node-sample.service.
日志
# journalctl -u node-sample -- Logs begin at Thu 2013-11-21 19:05:17 UTC, end at Fri 2013-11-22 01:12:15 UTC. -- Nov 22 01:12:15 d02 systemd[1]: Starting node-sample.service... Nov 22 01:12:15 d02 systemd[1]: Started node-sample.service. Nov 22 01:12:30 d02 node-sample[7213]: Sample message from application
重启、停止等
强制重启:
# systemctl restart node-sample
停止应用程序:
# systemctl stop node-sample
如果应用程序死亡或被杀死,应用程序将自动重新启动:
# systemctl status node-sample node-sample.service Loaded: loaded (/etc/systemd/system/node-sample.service; enabled) Active: active (running) since Fri 2013-11-22 01:12:15 UTC; 35s ago Main PID: 7213 (node) CGroup: name=systemd:/system/node-sample.service └─7213 /home/srv-node-sample/.nvm/v0.10.22/bin/node /home/srv-nod... Nov 22 01:12:15 d02 systemd[1]: Started node-sample.service. # kill 7213 # systemctl status node-sample node-sample.service Loaded: loaded (/etc/systemd/system/node-sample.service; enabled) Active: active (running) since Fri 2013-11-22 01:54:37 UTC; 6s ago Main PID: 7236 (node) CGroup: name=systemd:/system/node-sample.service └─7236 /home/srv-node-sample/.nvm/v0.10.22/bin/node /home/srv-nod... Nov 22 01:54:37 d02 systemd[1]: node-sample.service holdoff time over, sch...t. Nov 22 01:54:37 d02 systemd[1]: Stopping node-sample.service... Nov 22 01:54:37 d02 systemd[1]: Starting node-sample.service... Nov 22 01:54:37 d02 systemd[1]: Started node-sample.service.
PID 已更改,表明应用程序确实已被终止并重新启动。
网络套接字
如果应用程序使用 websockets,则必须将以下行添加到 Nginx 配置中:
proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection "upgrade"; proxy_http_version 1.1;
并且 Nginx 必须重新加载:
# systemctl reload nginx