PM2 优雅退出
在日常开发过程中,经常会用到 pm2 来起到服务,甚至会用 watch 来实现热更新。
但上面这种模式并不适合用在生产环境中,因为 pm2 零延时重启,会导致正在处理的请求直接被销毁,如果数据库没加事务,直接就会导致数据库的数据不完整。
处理方法是延时 kill,参数是--kill-timeout
。
在启动的app.js
中添加SIGINT
的监听,并在回调中用剩余的timeout
时间处理数据。
1 |
|
启动方式如下:
1 |
|
重载就会触发。
1 |
|
实际问题
一般使用 pm2,我们是希望 pm2 给我们提供负载均衡,每次 pull 好代码,reload 一下就能升级到最新的服务,而不需要从 Nginx 上下手。但是默认情况下 pm2 直接重启会导致正在处理的请求丢失。所以我们希望 PM2 在重启前,可以先通知 App,并给足够的时间让 App 处理完正在处理的请求,并且不再接收新的请求,然后再重启服务。
我们可以把上面的例子改成这样。
1 |
|
global.app.running
为整个服务的全局变量,只要服务启动就赋值为true
,并且在所有理由拦截器中增加判断逻辑:只要true
时才接收请求,这样就能保证当global.app.running
为false
时,正在处理的请求不会被销毁,所有后来进入的请求都失败,从而保证数据库完整性。
但是这种拦截方式太过于粗暴,只是保证数据库完整,但是依然达不到平滑,平滑升级还有很多路要走。
参考
PM2 优雅退出
https://bubao.github.io/posts/84550d96.html