⤴Top⤴

PM2 自动化部署

博客分类: 后端

PM2 自动化部署

PM2 自动化部署

什么是 PM2

PM2 是一个 node 后台进程管理工具,你可以对进程进行 start、stop、restart 或者 delete 等操作,还可以支持性能监控、负载均衡等功能,同类型的还有 forever 等:

npm install pm2 -g
Feature Forever PM2
Keep Alive
Coffeescript  
Log aggregation  
API  
Terminal monitoring  
Clustering  
JSON configuration  

PM2 is daemon process manager that will help you manage and keep your application online ✅

常用命令

# 启动一个 node 程序
pm2 start index.js
# 启动并取别名
pm2 start app_h5/bin/www --name application1
# 在文件改变的时候会重新启动程序
pm2 start index.js --watch

# 中止进程,指定进程 id 或名称,
pm2 stop 0

# 删除进程,all 则删除所有
pm2 delete 0

# 查看详情
pm2 describe 0

# 查看进程的资源消耗情况
pm2 monit

# 重启进程,也可用 restart
# Use reload instead of restart for 0-seconds downtime reloads
# restart 是先 kill 然后重启,而 reload 反之,故不会停机
pm2 reload 0

# 查看日志
pm2 logs 0

# 集群 cluster 启动 - 负载均衡
# -i 表示 number-instances 实例数量
# max 表示 PM2 将自动检测可用 CPU 的数量 可以自己指定数量
pm2 start start.js -i max

# 查看监控界面,即 pm2 list
pm2 l

pm2

更新 pm2 的方法:

# 保存当前进程状态
pm2 save
# 全局安装
npm i -g pm2
# pm2 update is necessary in order to refresh the PM2 daemon
pm2 update

关于 pm2 save 的用法: pm2 save takes a snapshot of your currently running Node applications. You can then restore these applications using pm2 resurrect. This is useful because it means you don’t have to manually restart each application when you restart pm2 (such as a machine reboot). Instead, you can just have a script that calls pm2 resurrect and it’ll start up all the Node apps.

如何启动一个项目

我们在启动一个项目的时候,首先克隆到服务器上,并且设置好 nginx 代理配置文件,主要是 server_nameproxy_pass,举个例子:

# nginx 配置目录 - /usr/local/nginx/conf/vhost
server {
  listen  80;
  server_name m1.xxx.com;
  location / {
    proxy_pass http://127.0.0.1:3000;
    # ...
  }
}

当我们设置完配置文件后,需要运行以下命令来重启 nginx 使其生效:

# 使用 -c 的参数指定 nginx.conf 文件的位置
nginx -c /usr/local/nginx/conf/nginx.conf -s reload

接下来我们要通过 pm2 启动项目,并且端口号设定为配置的 3000:

PORT=3003 pm2 start xxx/bin/www --name myProject

需要注意的 PORT 是我们项目里面接收的端口号环境变量的字段,比如前台 node.js 代码:

// https://github.com/indexzero/nconf
// node.js configuration with files, environment variables, and so on
var nconf = require('nconf');

// Setup nconf to use (in-order):
//   1. Command-line arguments
//   2. Environment variables
//   3. A file located at 'path/to/config.json'
//
nconf.argv()
  .env()
  .file({ file: 'path/to/config.json' });

nconf.defaults({
  'PORT': 2333, // 默认端口号
});

// Get port from environment and store in Express.
var port = nconf.get('PORT')

app.set('port', port);

这样之后,我们项目就成功启动了。大功告成 hooray!😊

自动化部署

一般情况下,我们项目部署在服务器上,但是有个问题,就是每次要更新的话必须在服务器上去操作,然后 pm2 reload 重启该进程,这样显然比较麻烦,因此我们可以借助 pm2 deploy 来进行自动化部署。具体可以参照 pm2 官方文档 Deployment 一节

1、 Generate a sample ecosystem.json file that lists the processes and the deployment environment.

pm2 ecosystem

自动会创建 ecosystem.json 文件,当然也支持 yaml 配置文件,然后在对应位置自定义即可:

{
  // Applications part
  "apps" : [{
    "name"      : "API",
    "script"    : "app.js",
    "env": {
      "COMMON_VARIABLE": "true"
    },
    // Environment variables injected when starting with --env production
    // http://pm2.keymetrics.io/docs/usage/application-declaration/#switching-to-different-environments
    "env_production" : {
      "NODE_ENV": "production"
    }
  },{
    "name"      : "WEB",
    "script"    : "web.js"
  }],
  // Deployment part
  // Here you describe each environment
  "deploy" : {
    "production" : {
      "user" : "node",
      // Multi host is possible, just by passing IPs/hostname as an array
      "host" : ["212.83.163.1", "212.83.163.2", "212.83.163.3"],
      // Branch
      "ref"  : "origin/master",
      // Git repository to clone
      "repo" : "git@github.com:repo.git",
      // Path of the application on target servers
      "path" : "/var/www/production",
      // Can be used to give options in the format used in the configura-
      // tion file.  This is useful for specifying options for which there
      // is no separate command-line flag, see 'man ssh'
      // can be either a single string or an array of strings
      "ssh_options": "StrictHostKeyChecking=no",
      // To prepare the host by installing required software (eg: git)
      // even before the setup process starts
      // can be multiple commands separated by the character ";"
      // or path to a script on your local machine
      "pre-setup" : "apt-get install git",
      // Commands / path to a script on the host machine
      // This will be executed on the host after cloning the repository
      // eg: placing configurations in the shared dir etc
      "post-setup": "ls -la",
      // Commands to execute locally (on the same machine you deploy things)
      // Can be multiple commands separated by the character ";"
      "pre-deploy-local" : "echo 'This is a local executed command'"
      // Commands to be executed on the server after the repo has been cloned
      "post-deploy" : "npm install && pm2 startOrRestart ecosystem.json --env production"
      // Environment variables that must be injected in all applications on this env
      "env"  : {
        "NODE_ENV": "production"
      }
    },
    "staging" : {
      "user" : "node", // 登录用户名
      "host" : "212.83.163.1", // 要部署的目标服务器 ip/域名
      "ref"  : "origin/master", // 用于部署代码时的分支
      "repo" : "git@github.com:repo.git", // git 仓库地址
      "path" : "/var/www/development", // 在目标服务器上部署的文件目录地址
      "ssh_options": ["StrictHostKeyChecking=no", "PasswordAuthentication=no"],
      "post-deploy" : "pm2 startOrRestart ecosystem.json --env dev", // 部署后启动的脚本
      "env"  : {
        "NODE_ENV": "staging"
      }
    }
  }
}

2、Be sure that you have the public ssh key on your local machine

ssh-keygen -t rsa
ssh-copy-id node@myserver.com

ssh-keygen 自动生成公钥和私钥,ssh-copy-id 命令将公钥传送到远端服务器,可以查看之前这篇博客 👈

3、Now initialize the remote folder with:

# 首次部署,该命令会在远端服务器上创建文件目录
pm2 deploy <configuration_file> <environment> setup

# demo
pm2 deploy ecosystem.json production setup

4、Deploy your code

# 再次部署,会上传项目代码,并用 PM2 启动
# 以后都用此命令进行更新代码和部署即可
pm2 deploy ecosystem.json production

注意:本地和服务器确保都安装 PM2

当然 deploy 命令也支持其他一些参数:

# pm2 deploy help

setup                run remote setup commands
update               update deploy to the latest release
revert [n]           revert to [n]th last deployment or 1
curr[ent]            output current release commit
prev[ious]           output previous release commit
exec|run <cmd>       execute the given <cmd>
list                 list previous deploy commits
[ref]                deploy to [ref], the "ref" setting, or latest tag
# Update remote version
pm2 deploy production update

# Revert to -1 deployment
pm2 deploy production revert 1

# execute command on remote machines
pm2 deploy production exec "pm2 reload all"

与 Nginx 的配合使用

下面是一个官网的 demo,Nginx 将 80 端口代理到 3001 端口,更多可以参照 Nginx 这篇博客:

upstream my_nodejs_upstream {
  server 127.0.0.1:3001;
  keepalive 64;
}

server {
  listen 443 ssl;

  server_name www.my-website.com;
  ssl_certificate_key /etc/ssl/main.key;
  ssl_certificate     /etc/ssl/main.crt;

  location / {
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header Host $http_host;

    proxy_http_version 1.1;
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection "upgrade";

    proxy_pass http://my_nodejs_upstream/;
    proxy_redirect off;
    proxy_read_timeout 240s;
  }
}

nodemon / supervisor

两种常用于开发环境监听文件改动并重启服务的方式,还可以搭配 Browsersync 实现客户端自动刷新:

nodemon index.js

# 也可省略写法,默认找 index.js
nodemon