当代 Nodejs 项目开发完毕,一般前端和后台都是分离的,所以部署项目的时候就会涉及同时启动和管理多个进程(比如前台启动一个进程,运行在8001端口,后台代码另外启动一个进程,运行在8002端口)的工作。解决这个问题,以前我用 tmux 多一些,但是本期推荐的是另外一个工具,叫做 PM2 。
PM2 ( Process Manager ,进程管理器)可以帮我们很方便的启动多个进程,进程崩溃自动重启,也可以帮我们创建系统启动脚本,这样,机器重启了,我们的项目也可以自动重启。
注意:本期的内容适合部署《 React 手牵手》 中的案例项目。
Ubuntu v14.04
Node.js v5.4.1 版本以上
Nginx v1.4.6
PM2 v2.1.5
安装 Nodejs 可以参考 《 Nodejs 乐高》 。 Ubuntu 命令行使用可以参考 《驾驭命令行怪兽》 。上面的包版本没有硬性要求,只要相近的版本应该操作都类似。
登录到服务器,安装 PM2 包:
npm install -g pm2
前端 index.html 代码如下:
var express = require('express');
var app = express();
var axios = require('axios');
app.get('/', function(req, res) {
axios.get('http://localhost:8002/content').then(function(response){
res.send(response.data.content);
});
})
app.listen(8001, function() {
console.log('express server is running on port 8001');
});
代码上传到服务器,一般都是采用 github 的形式,但是作为 demo ,我这里直接使用 scp 命令了
scp -r pm2-demo haoqicat.com
准备工作完成后,这时到服务器上运行 node index.js
命令就能让前端代码跑起来了。但是当我们退出登录服务器的时候,node server.js
命令会终止运行。要解决这个问题,就要用到 PM2 。
后端 index.js 内容如下:
var express = require('express');
var app = express();
var cors = require('cors');
app.use(cors());
app.get('/content', function(req, res) {
res.json({ content: 'Content From Server API' });
})
app.listen(8002, function() {
console.log('express server is running on port 8002');
});
进入后端代码目录,安装 npm 包
cd server
npm install
这时运行 node index.js
命令,后端 API 服务就生效了。同样的问题,node index.js
不能长久运行,因此用 PM2 启动后端代码。
现在,我们有前端和后端两个 Node.js 应用需要启动,所以在 Home 目录下,新建一个 app.json
文件,内容如下:
{
"apps": [{
"name": "api",
"script": "server/index.js"
},{
"name": "front-end",
"script": "client/index.js"
}]
}
这个 app.json
文件将作为参数传递给 pm2 start
命令,如下:
pm2 start app.json
这样,前端和后端两个应用就都运行起来了。
配置一个域名指向当前服务器,然后到 /etc/nginx/sites-enabled 目录下, 删除一个默认文件:
sudo rm default
然后,新建一个 client.conf 配置文件对应前端展示页面的网址:
cd /etc/nginx/sites-enabled
sudo touch client.conf
这个 client.conf 文件的内容如下:
server {
listen 80;
server_name clientpm2.haoqicat.com;
location / {
proxy_pass http://localhost:8001;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header Host $http_x_forwarded_host;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_read_timeout 3m;
proxy_send_timeout 3m;
}
}
在同一目录下,再添加对应后端 API 地址的配置文件 server.conf,文件内容如下:
server {
listen 80;
server_name serverpm2.haoqicat.com;
location / {
proxy_pass http://localhost:8002;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header Host $http_x_forwarded_host;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_read_timeout 3m;
proxy_send_timeout 3m;
}
}
修改 Nginx 的配置文件之后,需要执行下面命令,配置信息才能生效:
sudo service nginx reload
上面的步骤做完,pm2 已经成功为我们管理了2个不同的前后端进程,网站已经可以正确访问了。 但是现在的问题是,如果 ubuntu 系统重启了,那么我们的应用就会死掉。要解决这个问题,可以用添加 pm2 启动脚本的形式。
让 PM2 根据系统信息,自动生成启动脚本,先执行命令:
pm2 startup
当上面命令运行之后,会自动打印出类似如下一行命令信息,xxx
会被您自己的登录用户名代替,直接复制这行命令,在命令行中粘贴运行就可以。
sudo su -c "env PATH=$PATH:/home/xxx/.nvm/v6.3.1/bin pm2 startup linux -u ubuntu --hp /home/xxx"
当上面命令执行之后,在系统 /etc/init.d/
目录下,出现一个 pm2-init.sh
文件,即为 PM2 的启动脚本,当服务器重启的时候,会运行 pm2-init.sh
文件,从而启动 PM2。
详细文档参考 启动脚本
用 kill -9
来杀死一个进程,会发现根本杀不死。因为 pm2 的一个优点就是:一旦发现我们的应用进程死了,会自动帮我们重启。
另外,重启我们的 ubuntu 机器,因为前面 PM2 已经为我们创建了启动脚本,所以项目也可以自动重启。