今天這篇文章主要來介紹下 Nginx 的 reload 流程。實際上在以前文章中,在更改了 nginx 配置文件時,咱們都會執行 nginx -s reload 命令,咱們執行這條命令的緣由是但願 nginx 不中止服務始終在處理新的請求的同時把 nginx 的配置文件平滑的把舊的 nginx.conf 配置更新爲新的 nginx.conf 配置。linux
這樣一個功能對於 nginx 很是有必要,可是有時候咱們會發如今執行 nginx -s reload
命令後,worker 子進程的數量會變多了,這是由於老的配置運行的 worker 進程長時間沒有退出,當使用 stream 作四層反向代理的時候,可能這種場景會更多。nginx
那麼下面咱們經過分析 nginx 的 reload 流程,來探究下 nginx 到底作了些什麼?所謂優雅的退出和當即退出有什麼區別?segmentfault
第一步在修改好 nginx 的配置文件 nginx.conf 後,向 master 進程發送 HUP 信號,這實際上和咱們在命令行執行 nginx -s reload
命令效果是同樣的。spa
那麼 master 進程在收到 HUP 信號之後,會在第二步檢查咱們的配置文件語法是否正確,也就是說咱們並不必定非要在 nginx -s reload 前執行 nginx -t 檢驗下語法是否正確,由於在第二步 nginx 的 master 進程必定會執行這個步驟。操作系統
在 nginx 的配置語法所有正確之後,master 進程會打開新的監聽端口,爲何要在 master 進程中打開新的監聽端口?由於咱們可能在 nginx.conf 中會引入新的例如 443 或者以前咱們沒有打開的的監聽端口,而全部 worker 進程是 master 進程 的子進程,子進程會繼承父進程全部已經打開的端口,這是 linux 操做系統定義的,因此第三步,咱們 master 進程打開了可能引入的新的監聽端口。命令行
接下來 mster 進程會用新的 nginx.conf 配置文件來啓動新的 worker 子進程,那麼老的 worker 子進程會怎麼樣呢?代理
咱們會在第五步在啓動新的 worker 子進程之後,由 master 進程再向老 worker 子進程發送 QUIT 信號,QUIT 信號和 TERM,INT 信號是不同的,QUIT 信號是請優雅地關閉子進程,這時候須要關注順序,由於 nginx 須要保證平滑,因此要先啓動新的 worker 子進程,再向老的 worker 子進程發送 QUIT 信號。code
那麼老的 master 子進程收到 QUIT 信號後,首先關閉監聽句柄,也就是說這個時候新的鏈接只會到新的 worker 子進程,因此雖然他們之間有時間差,可是時間是很是快速的,那麼關閉監聽句柄後,處理完當前鏈接後就結束進程。blog
下面看 reload 不停機載入新配置的圖示。繼承
master 進程上原先有四個綠色的 worker 子進程,它們使用了老的配置,當咱們更改了 nginx.conf 配置文件後,向 master 發送 SIGHUP 信號或者執行 reload 命令, 而後 master 會用新的配置文件啓動四個新的黃色 worker 子進程,此時是四個老的綠色 worker 子進程和四個新的黃色的 worker 子進程是並存的。那麼老的 worker 子進程在正常的狀況下會在處理已經創建好的鏈接上的請求以後關閉這個鏈接,哪怕這個鏈接是 keeplive 請求也會正常關閉。
可是異常狀況,若是有一些請求出現問題,客戶端長時間沒法處理,那麼就會致使這個請求長時間停留在這個 worker 子進程當中,那麼這個 worker 子進程會長時間存在,由於新的鏈接已經跑在黃色的 worker 子進程中,因此影響並不會很大,惟一會影響的就是綠色的 worker 子進程會長時間存在,但也隻影響已存在的鏈接,不會影響新的鏈接。
咱們有什麼辦法處理呢?在新版本中提供了一個新的配置 worker_shutdown_timeout,也就是說最長等待多長時間,這樣 master 進程啓動新的黃色 worker 進程以後,若是老的 worker 進程一直沒有退出,時間到了以後會強制把老的 worker 進程退出掉。
本文主要講解了 Nginx 平滑升級新的配置文件的流程,在咱們瞭解了優雅關閉 worker 子進程和啓動新配置的 worker 子進程流程間的關係後,咱們能夠更好地處理罕見的異常場景。