pm2:从小白到写出一键部署前后端工程

背景

基于公司KPI自我学习进步,以及我本人是负责后台管理系统开发维护的大环境背景下,我决定研究并开发了,拖拽生成代码的工具,目前完成的功能有: 拖拽生成 Table 页面和拖拽自动生成 Form 表单。

    1. 拖拽生成 Table 页面
    • 拖拽组件,从菜单栏到中间区域,或者同区域内更换位置,不同区域可以更换,只是目前,没有一个组件是会同时可以出现在 2 个区域的,所以此功能暂时无法看到;
    • 单击编辑属性
    • 右击删除
    • 生成代码
      • 可直接复制
      • 可生成文件并下载 zip 包
    1. 拖拽自动生成 Form 表单
      拖拽生成 form 表单,从左侧菜单栏中,将 form 元素拖到中间区域,可根据右上角的「N 列布局」输入你想要的 N 列布局,中间区域的各个 form 表单元素,可自由拖拽更换位置。可以点击这里来使用。此功能第一个版本可以看到的有:
    • 可以生成是单列,双列或者 N([1,10]) 列
    • 可以拖拽生成组件
    • 添加普通校验:必填
    • 单击编辑属性
    • 右击删除
    • 生成代码
      • 可直接复制
      • 可生成文件并下载 zip 包
    • 解决拖拽过程中定位不准确的 bug

简介

该项目前后端分离,前端是react写的,后端是node写的一个非常小的服务,用于生成目录文件,以及压缩zip包来下载生成的代码。写这个项目也主要是为了自己走一遍前端从开发到部署的所有流程。

本人主业是前端工程师,node是自己感兴趣想学的,所以写的只能说功能上还能用,代码质量渣的xx。

学习步骤

项目目录介绍


image.png

原始农业

刚开始,只为满足功能,能跑起来就OK。
纯手工部署。步骤如下:

前端部分

先登录服务器,将,代码git clone 下来,然后cd service目录下执行npm install

# 在本地项目执行命令
# 正确来说,应该在服务器上执行这个命令,鉴于我的阿里云服务器内存很小,就在本地执行。但是基于工作经历来说,我们有的线上项目,大型后,在线上服务器进行build也会很慢,有时候还会卡死,所以在本地build也没什么薄饼。
npm run build

# 拷贝(在本地执行)
# 服务器上的路径,/srv/front,直接将文件夹重命名为front
# 注意:一定要在该项目目录下进行
scp -r build root@ssh [email protected].**.**:/srv

# 在服务器执行
# 登录服务器
ssh [email protected]
cd /srv/
# 删除旧的文件
rm -rf front/
# 重命名build为front
mv build front

后端部分

# 登录远程服务器
ssh [email protected]

# 更新代码
cd /srv/bms-code-auto-generate
git pull origin master

# 远程启动后端,如果已经启动着,需要先关闭再重新启动
nohup node index.js &
# 关闭后端服务
ps aux | grep node
kill -9 pid

近代农业

等完成部署后,就发现这样每次都很麻烦,因为不想每次更新了代码,再去手动重启一遍node,这时候想起来了pm2,它可以在监控到文件更新后,去自动重启服务,所以就想着应用上pm2。

PM2 是一个守护进程管理器,它将帮助您管理和保持您的应用程序 24/7 在线。
nodejs的高级生产流程管理器。

也有其他解释:

而pm2是基于nodejs开发的进程管理器,适用于后台常驻脚本管理,同时对node网络应用有自建负载均衡功能。官方的说法,pm2 是一个带有负载均衡功能的Node应用的进程管理器,个人认为,并不准确,因为pm2支持多种语言,只是对于除node之外的其他进程无负载均衡的能力。 - 知乎

第一版 简单使用pm2 去启动index.js文件

在服务器上。

# 启动后端服务,pm2版本,
## 全局安装pm2
npm install -g pm2
## 改用pm2来启动程序--watch表示,监控程序运行状态,一旦:服务异常:自动重启;服务发生变化:自动重启
pm2 start index.js --watch

这样启动的node进程,有个问题,就是我的下载文件xxx.zip文件是保存在tmp目录下,每当我一点下载的时候,node进程就会重启。

image.png

重启的时候有时候会导致下载链接失败。


image.png

这是在请教做node的同学时的聊天截图继续,所以moduleName一个是cvb,下载的zip文件名确是666600.zip,有点对不上,因为不是同一个时间段的,是后来写文的时候翻看的聊天记录。

后来发现,去掉--watch不会重启,并且下载链接不会报错,但是,这时候,又出现了一个问题,就是,当代码有更新时,node服务并不会自动重新启动,这就又回到了“原始农业”时代,我觉得应该监控文件是可配置的,这时候发现,得去学习一下pm2啦,于是我去翻看了pm2的官方文档,找到了ignore_watchecosystem.config.js文件。

于是有了,在/service/目录下添加文件:ecosystem.config.js

image.png

将代码更新到服务上去后,可以使用命令pm2 start ./service/ecosystem.config.js 进行启动,这样启动的就比较方便了。

备注

pm2起的项目路径这样的:


image.png

在其中是会包含current和source的。我们需要手动,在source下,添加git仓库的地址,项目源码是在这里面的。

current -- 当前服务运行的文件夹(是source的软链接)
share -- log pid 等共享数据 (我目前的项目中没有这个文件)
source -- clone 下来的源代码
-- 友

现代农业

虽然上面的后端部署方式有了很大的改进,但是还是有个弊端就是,需要每次登陆服务器并且去手动拉代码,这样很麻烦。

于是写了一个一键部署的命令。

后端 v1.0

在原有的文件:ecosystem.config.js中进行扩展。

module.exports = {
    apps: [
        {
            name: 'generate',
            script: './index.js',
            // instances: 1,
            watch: true,
            ignore_watch: ['[/\\]./', 'node_modules', 'tmp']
        }
    ],
    deploy: {
        daily: {
            user: 'root',
            host: ['47.105.xx.xx'],
            ref: 'origin/node',
            repo: '[email protected]:springHyc/bms-code-auto-generate.git',
            path: '/srv/hehe/bms-code-auto-generate3',
            'post-deploy': 'git pull && cd service &&   npm install && npm run daily',
            env: {
                NODE_ENV: 'daily'
            }
        }
    }
};

配合package.json中添加命令:

"scripts": {
        "daily": "NODE_ENV=daily  pm2 startOrRestart ecosystem.config.js"
    },

这样直接在本地运行:pm2 deploy ./service/ecosystem.config.js daily,即可完成,自动拉取最新的代码,并且完成重启目的。

在第一次执行前,应该进入目录/srv/hehe/bms-code-auto-generate3中,手动新建mkdir source这个文件夹,不然后报错。

image.png

然后还要将/srv/hehe/bms-code-auto-generate3目录下clone项目git clone origin [email protected]:***c/bms-code-auto-generate.git,再将项目名称更改为source

后端 v2.0

上面的方式,仍然不太好,因为在本地运行的时候,ecosystem.config.js文件是放在./service/目录下的,我们能不能将ecosystem.config.js文件放在根目录下呢?继续研究试验...

在根目录下新建ecosystem.config.js文件:

// 在v1.0版本和v2.0版本中,我们将命令的名字做了更改。
module.exports = {
    apps: [
        {
            name: 'node-generate',
            script: './index.js',
            cwd: './service/',
            watch: false,
            log_date_format: 'YYYY-MM-DD HH:mm Z'
        }
    ],
    deploy: {
        daily: {
            user: 'root',
            host: ['47.105.**.**'],
            ref: 'origin/node',
            repo: '[email protected]:springHyc/bms-code-auto-generate.git',
            path: '/srv/hehe/bms-code-auto-generate3',
            'post-deploy': 'git pull && cd service && npm install && cd ../ && npm run deploy-node',
            env: {
                NODE_ENV: 'daily'
            }
        }
    }
};

配合package.json中添加命令:

"deploy-node": "NODE_ENV=daily pm2 startOrRestart ecosystem.config.js",
"deploy-end": "pm2 deploy ecosystem.config.js daily",

这样在本机根目录下执行npm run deploy-end即可完成,自动拉取最新的代码,并且完成重新部署的目的。

前端

至于前端代码,我们没有做build相关的优化,所以前端代码的打包很简单,只需要build,然后将build出来的build/目录拷贝到服务器的某个位置,like: /srv/hehe/bms-code-auto-generate3/build,然后配置好ngnix代理即可。

手动部署的命令是:

# 在本地项目执行命令
# 正确来说,应该在服务器上执行这个命令,鉴于我的阿里云服务器内存很小,就在本地执行。但是基于工作经历来说,我们有的线上项目,大型后,在线上服务器进行build也会很慢,有时候还会卡死,所以在本地build也没什么薄饼。
npm run build

# 拷贝(在本地执行)
# 服务器上的路径,/srv/front,直接将文件夹重命名为front
# 注意:一定要在该项目目录下进行
scp -r build root@ssh [email protected].**.**:/srv/hehe/bms-code-auto-generate3

那我们能不能写个命令让它自动执行呢?可以啊

就是这个,在package.json中添加命令:

"deploy-front": "npm run build && scp -r build [email protected].**.**:/srv/hehe/bms-code-auto-generate3",

那现在我们执行npm run deploy-front就可以部署前端啦。

那现在有想了,我们可不可以把前后端部署命令合并成一个命令呢?分开都麻烦啊☹️

于是就有了这个命令,在package.json中添加命令:

"deploy": "npm run deploy-end && npm run deploy-front"
现在我们执行npm run deploy就可以自动部署前后端啦。


前端部署还有一种方式,是直接在服务器上build的,由于我们有内部包的限制,外网无法访问通,所以上面我一直采用的是本地build的方式。

服务器上build方式为:

// ecosystem.config.js文件中添加
deploy: {
        daily2: {
            user: 'root',
            host: ['47.105.**.**'],
            ref: 'origin/node',
            repo: '[email protected]:springHyc/bms-code-auto-generate.git',
            path: '/srv/hehe/bms-code-auto-generate3',
            'post-deploy': 'git pull && npm i --registry=http://shuqudata.registry.com && npm run build',
            env: {
                NODE_ENV: 'daily2'
            }
        }
    }
// package.json中添加
 "deploy-front-remote": "pm2 deploy ecosystem.config.js daily2",

然后执行npm run deploy-front-remote即可。
这个地方注意,build后,build文件路径在/source/根目录下,要进行nginx配置才可以访问。

备注

为什么我会把项目/srv/hehe/bms-code-auto-generate3放在这个目录上呢,因为这是个从无到有的尝试过程,我原本在/srv/是手动起着一套前后端的,我不想破坏正在启动着的应用。

  • 服务上ngnix配置
# 路径:/etc/nginx/sites-enabled/
# 文件名:hehe-bms (其实是随便起的,只是为了试验)
server {
        listen       8080;
        server_name  47.105.**.**;

    location /api {
            proxy_pass  http://localhost:3003; // 后端地址
        }

    location / {
        root /srv/hehe/bms-code-auto-generate3/build/; // 前端路径
        index index.html index.htm;
            try_files $uri $uri/ /index.html;
        }
}

注意,nginx配置修改后,一定要重启nginx,不然不生效。重启命令nginx -s rolad,想要学习有关nginx的命令请看我的总结。

  • ecosystem.config.js
module.exports = {
    apps: [
        {
            name: 'node-generate',
            script: './index.js',
            cwd: './service/',
            watch: false,
            log_date_format: 'YYYY-MM-DD HH:mm Z'
        }
    ],
    deploy: {
        daily: {
            user: 'root',
            host: ['47.105.**.**'],
            ref: 'origin/node',
            repo: '[email protected]:springHyc/bms-code-auto-generate.git',
            path: '/srv/hehe/bms-code-auto-generate3',
            'post-deploy': 'git pull && cd service && npm install && cd ../ && npm run deploy-node',
            env: {
                NODE_ENV: 'daily'
            }
        }
    }
};

  • package.json
{
    "name": "bms-code-auto-generate",
    "version": "0.2.0-alpha0.1",
    "private": true,
    "scripts": {
        "dev": "node scripts/start.js",
        "build": "node scripts/build.js",
        "test": "node scripts/test.js",
        "deploy-node": "NODE_ENV=daily pm2 startOrRestart ecosystem.config.js",
        "deploy-end": "pm2 deploy ecosystem.config.js daily",
        "deploy-front": "npm run build && scp -r build [email protected].**.**:/srv/hehe/bms-code-auto-generate3",
        "deploy": "npm run deploy-end && npm run deploy-front"
    },
...
}
  • pm2 命令
命令 含义
pm2 stop id/name 暂停
ps aux | grep node 查看node进程
pm2 list 查看pm2启动列表
pm2 start index2.js --watch 启动项目
pm2 logs 查看日志
pm2 restart app_name 杀死并重新启动进程。restart = stop+start
pm2 reload app_name reload实现了0秒的停机时间重新加载.reload = 重新读取配置文件
pm2 stop app_name
pm2 delete app_name
pm2 flush | pm2 flush 清空 PM2 管理的当前应用程序日志
pm2 monit 监控CPU/内存

你可能感兴趣的:(pm2:从小白到写出一键部署前后端工程)