基于PM2实现的NodeJS无损发布
什么是无损发布
无损发布即服务部署过程中,对用户来说是无感知的,不会对用户产生任何影响。
为什么需要无损发布
很多服务更新都需要在大半夜进行,尤其在一些创业小公司,晚上访问服务的用户较少甚至没有,这个时候更新服务影响范围较小。当我们引入无损发布后,可以随时发布而不用在大晚上进行部署
对于前端NodeJS如何实现无损发布
首先看一个普通的NodeJs服务
通过网关实现流量的均衡分发,到达具体的一台实例机器上,通过PM2进行NodeJs服务的管理,开辟多个进程
服务更新发布时,以Server1为例:
-
GateWay 下掉Server1, 停止流量访问Server,将其流量转发到其他机器
-
Server1 停服,升级,重启等操作
-
Server1更新完成验证OK时,GateWay 再切回流量访问Server1
其中有个问题:虽然GateWay拦截了Server1的后续请求,但是不能保证当前正在访问的请求。此时如果进行服务更新,则会影响当前用户的访问。
例如:当你在正在编辑一批重要繁琐的资料时,点击提交,结果服务挂了,需要重新填写提交时,此时你的心里。。。
问题:如何确保当前没有访问的请求
- 等上十秒半分钟后再进行操作(这个时间段后请求基本都处理完成了)
- 除了延迟等待这种方式,我们可以通过PM2来实现当前请求的记录
PM2/IO
通过PM2/IO 来进行统计,创建一个名称为CounterText的计数器,请求进来时计数增加,请求结束时计数递减

注:@pm2/io 的功能比较多,而只用自定义Metrics相关功能,可以使用tx2,更轻量
pm2 show 0
查看单个进程的内存变量,例如查看第一个进程数据 PM2 show [options] <name|id>,可以看到Metrics 模块里面有CounterTest 的变量,对应的值则为当前活跃的请求数。

pm2 list
以上只是通过控制台命令输出的单个进程的数据,通过PM2 对应的API查看所有进程的数据
const pm2 = require("pm2");
pm2.list((err, list) => {
if (err) return false;
list.forEach((item) => {
console.log(item);
});
});
每个实例对象上包含了pm2_env, 在其axm_monitor属性中可以发现定义的CounterTest。

以上代码是通过遍历每个进程打印出的数据,所以要统计当前的活跃请求,需要累加每个进程上的CounterTest 属性值。
注:如果请求量少,在个别进程上不会存在CounterTest 属性,需要做判空处理,不能直接获取CounterTest.value
总结
无损发布,需要网关与服务相互配合。在服务侧,更核心的是判断是否存在活跃的请求。再通过对该功能进行接口的封装输出,提供给网关活工具平台。进而实现自动化部署。
转载自:https://juejin.cn/post/7243757233665376315