博客 / 詳情

返回

PM2 優雅退出

在日常開發過程中,經常會用到 pm2 來起到服務,甚至會用 watch 來實現熱更新。

但上面這種模式並不適合用在生產環境中,因為 pm2 零延時重啓,會導致正在處理的請求直接被銷燬,如果數據庫沒加事務,直接就會導致數據庫的數據不完整。

處理方法是延時 kill,參數是--kill-timeout。

在啓動的app.js中添加SIGINT的監聽,並在回調中用剩餘的timeout時間處理數據。

process.on('SIGINT', function() {
   db.stop(function(err) {
     process.exit(err ? 1 : 0)
   })
})

啓動方式如下:

pm2 start app.js --kill-timeout 3000

重載就會觸發。

pm2 reload

實際問題

一般使用 pm2,我們是希望 pm2 給我們提供負載均衡,每次 pull 好代碼,reload 一下就能升級到最新的服務,而不需要從 Nginx 上下手。但是默認情況下 pm2 直接重啓會導致正在處理的請求丟失。所以我們希望 PM2 在重啓前,可以先通知 App,並給足夠的時間讓 App 處理完正在處理的請求,並且不再接收新的請求,然後再重啓服務。

我們可以把上面的例子改成這樣。

process.on('SIGINT', function() {
    global.app.running = false;
    db.stop(function(err) {
        process.exit(err ? 1 : 0)
   })
})

global.app.running為整個服務的全局變量,只要服務啓動就賦值為true,並且在所有理由攔截器中增加判斷邏輯:只要true時才接收請求,這樣就能保證當global.app.running為false時,正在處理的請求不會被銷燬,所有後來進入的請求都失敗,從而保證數據庫完整性。

但是這種攔截方式太過於粗暴,只是保證數據庫完整,但是依然達不到平滑,平滑升級還有很多路要走。

參考鏈接

Graceful Stop

user avatar
0 位用戶收藏了這個故事!

發佈 評論

Some HTML is okay.