【Nginx】不中斷現有鏈接,平滑升級Nginx

首先讓咱們瞭解一下各類信號的意義,咱們後面會用到其中的幾個:nginx

TERM,INT 快速退出日誌

QUIT 優雅退出(等待全部鏈接關閉後再退出程序,不接受新的鏈接)code

HUP 在修改配置後,以新的配置啓動worker進程,優雅退出舊的worker進程進程

USR1 從新打開日誌文件源碼

USR2 更新二進制文件編譯

WINCH 優雅地關閉worker進程(但不關閉master)ast

接下來是步驟:配置

1. 編譯、得到新的二進制文件

這一步很簡單,新版本Nginx或者舊版本Nginx源碼加上新的編譯參數,在通過configuremake後,咱們在源碼目錄下的objs目錄中找到新的nginx二進制文件。二進制

注意,接下來請不要make install請求

2. 備份與替換

將舊的nginx二進制文件備份一下:

cd /usr/local/nginx/sbin
mv nginx nginx.old

而後將上一步獲得的新版本二進制文件複製過來:

cp /path/to/source/nginx /usr/local/nginx/sbin/

3. USR二、WINCH與QUIT

發送USR2信號給master進程

kill -USR2 `cat /usr/local/nginx/logs/nginx.pid`

這一步發生了什麼?

master進程首先重命名PID文件,在文件名後添加.oldbin後綴,好比nginx.pid會被重命名爲nginx.pid.oldbin。接着依次啓動新的執行文件和新的worker進程。這時候咱們觀察系統的進程,能夠看到有兩個master進程:

PID  PPID USER    %CPU   VSZ WCHAN  COMMAND
33126     1 root     0.0  1164 pause  nginx: master process /usr/local/nginx/sbin/nginx
33134 33126 nobody   0.0  1368 kqread nginx: worker process (nginx)
33135 33126 nobody   0.0  1380 kqread nginx: worker process (nginx)
33136 33126 nobody   0.0  1368 kqread nginx: worker process (nginx)
36264 33126 root     0.0  1148 pause  nginx: master process /usr/local/nginx/sbin/nginx
36265 36264 nobody   0.0  1364 kqread nginx: worker process (nginx)
36266 36264 nobody   0.0  1364 kqread nginx: worker process (nginx)
36267 36264 nobody   0.0  1364 kqread nginx: worker process (nginx)

注意這兩個master進程的PID:第一個進程的PPID是1,這是舊master進程,而新master進程的PPID就是舊master進程的PID,這說明新的master來自於舊的master。

這時候,新舊兩種worker同時接受鏈接請求。

發送WINCH給舊master

接下來,發送WINCH信號給舊的master進程來「優雅」地關閉舊的Nginx worker:

kill -WINCH `cat /usr/local/nginx/logs/nginx.pid.oldbin`

過一段時間,咱們觀察系統進程:

PID  PPID USER    %CPU   VSZ WCHAN  COMMAND
33126     1 root     0.0  1164 pause  nginx: master process /usr/local/nginx/sbin/nginx
36264 33126 root     0.0  1148 pause  nginx: master process /usr/local/nginx/sbin/nginx
36265 36264 nobody   0.0  1364 kqread nginx: worker process (nginx)
36266 36264 nobody   0.0  1364 kqread nginx: worker process (nginx)
36267 36264 nobody   0.0  1364 kqread nginx: worker process (nginx)

新舊兩個master進程都在,可是worker都是來自於新master。

那麼爲何咱們不直接用-QUIT退出舊master呢?由於假如這時咱們發現新worker進程由於一些緣由沒法接受請求,那咱們就能快速啓動舊Nginx。

快速回退的方法見最後。

QUIT退出舊master

升級很成功,新worker正常接受請求,那麼咱們就能夠關掉舊master了:

kill -QUIT `cat /usr/local/nginx/logs/nginx.pid.oldbin`

觀察系統進程:

PID  PPID USER    %CPU   VSZ WCHAN  COMMAND
36264     1 root     0.0  1148 pause  nginx: master process /usr/local/nginx/sbin/nginx
36265 36264 nobody   0.0  1364 kqread nginx: worker process (nginx)
36266 36264 nobody   0.0  1364 kqread nginx: worker process (nginx)
36267 36264 nobody   0.0  1364 kqread nginx: worker process (nginx)

咱們看到,新master進程其PPID已經變成了1。

4. 快速回退

若是咱們在發送WINCH給舊master進程後發現新master沒法正常工做,咱們須要可以快速回退。

咱們通常用兩種方案來快速回退。

  1. 發送HUP信號給舊master進程。舊master進程會在不從新讀取配置文件的狀況下直接啓動新的worker進程。而後就能夠發送QUIT信號給新master進程,使全部新進程能夠優雅退出。
  2. 發送TERM信號給新master進程。新master進程發送信號關閉全部的worker進程(若是由於某些緣由新的進程沒有退出,就得發送KILL信號強制退出了)。當新master進程退出後,舊master進程會自動啓動它的worker進程。
相關文章
相關標籤/搜索