一、背景
在伺服器開發過程中,難免需要重啟服務載入新的**或配置,如果能夠保證server重啟的過程中服務不間斷,那重啟對於業務的影響可以降為0。最近調研了一下nginx平滑重啟,覺得很有意思,記錄下來供有興趣的同學查閱。
二、重啟流程
三、nginx實現
為了驗證nginx平滑重啟,筆者首先嘗試nginx啟動的情形下再次開啟乙個新的server例項,結果如圖:
很明顯,重新開啟server例項是行不通的,原因在於新舊server使用了同乙個埠80,在未開始socket reuseport選項復用埠時,bind系統呼叫會出錯。nginx預設bind重試5次,失敗後直接退出。而nginx需要監聽ipv4位址0.0.0.0和ipv6位址[::],故圖中列印出10條emerg日誌。
接下來就開始嘗試平滑重啟命令了,一共兩條命令:
kill -usr2 `cat /var/run/nginx.pid`
kill -quit `cat /var/run/nginx.pid.oldbin`
第一條命令是傳送訊號usr2給舊的master程序,程序的pid存放在/var/run/nginx.pid檔案中,其中nginx.pid檔案路徑由nginx.conf配置。
第二條命令是傳送訊號quit給舊的master程序,程序的pid存放在/var/run/nginx.pid.oldbin檔案中,隨後舊的master程序退出。
那麼問題來了,為什麼舊的master程序的pid存在於兩個pid檔案之中?事實上,在傳送訊號usr2給舊的master程序之後,舊的master程序將pid重新命名,原先的nginx.pid檔案rename成nginx.pid.oldbin。這樣新的master進行就可以使用nginx.pid這個檔名了。
先執行第一條命令,結果如圖:
不錯,新舊master和worker程序並存了。 再來第二條命令,結果如圖:
如你所見,舊的masterwww.cppcns.com程序8527和其worker程序全部退出,只剩下新的master程序12740。
不由得產生困惑,為什麼手動開啟乙個新的例項行不通,使用訊號重啟就可以達到。先看下nginx log檔案:
除了之前的錯誤日誌,還多了一條notice,意思就是繼承了sockets,fd值為6,7。 隨著日誌翻看nginx原始碼,定位到nginx.c/ngx_exec_new_binary函式程式設計客棧之中,
ngx_pid_t
ngx_exec_new_binary(ngx_cycle_t *cycle, char *const *ar**)
*p = '\0';
env[n++] = var;
... env[n] = null;
... ctx.envp = (char *const *) env;
ccf = (ngx_core_con程式設計客棧f_t *) ngx_get_conf(cycle->conf_ctx, ngx_core_module);
if (ngx_rename_file(ccf->pid.data, ccf->oldpid.data) == ngx_file_error)
pid = ngx_execute(cycle, &ctx);
if (pid == ngx_invalid_pid)
}...
return pid;
}函式的流程為
static ngx_int_t
ngx_add_inherited_sockets(ngx_cycle_t *cycle)
if (ngx_array_init(&cycle->listening, cycle->pool, 10,
sizeof(ngx_listening_t))
!= ngx_ok)
for (p = inherited, v = p; *p; p++)
ngx_memzero(ls, sizeof(ngx_listening_t));
ls->fd = (ngx_socket_t) s;
}} ...
ngx_inherited = 1;
return ngx_set_inherited_sockets(cycle);
}函式流程為:
解析環境變數nginx_var的值,獲取fd存入陣列
fd對應的socket設為ngx_inherited,儲存這些socket的資訊。
也就是說,新的server壓根就沒重新bind埠listen,這些fd狀態和值都是新的master程序fork時帶過來的,新的master程序監聽處理繼承來的檔案描述符即可,這裡比較關鍵的一點在於listen socket檔案描述符通過env傳遞。
本文標題: nginx 平滑重啟的實現方法
本文位址: /jiqiao/fuwuqi/260762.html
nginx重啟 平滑重啟
進入 ngiinx sbin目錄下 nginx c usr local nginx conf nginx.conf c引數指定了要載入的nginx配置檔案路徑 停止操作 停止操作是通過向nginx程序傳送訊號來進行的 步驟1 查詢nginx主程序號 ps ef grep nginx在程序列表裡 面找...
nginx重啟 平滑重啟
進入 ngiinx sbin目錄下 nginx c usr local nginx conf nginx.conf c引數指定了要載入的nginx配置檔案路徑 停止操作 停止操作是通過向nginx程序傳送訊號來進行的 步驟1 查詢nginx主程序號 ps ef grep nginx 在程序列表裡 面...
nginx平滑重啟與平滑公升級的方法
如何實現nginx平滑重啟與平滑公升級?平滑重啟 kill hup cat usr local www nginx logs nginx.pid 平滑公升級nginx 得到編譯引數 用上面這段編譯 然後make,千萬別make install make完了 在objs目錄下就多了個nginx,這個就...