
點擊上方“武培軒”,選擇“設為星標”
技術文章第一時間送達!
之前我們講解 Nginx 命令行的時候,可以看到 Nginx 停止有兩種方式,分別是?nginx -s quit
?和?nginx -s stop
,其中 stop 是指立即停止 Nginx,而 quit 是指優雅的關閉 Nginx,對應的信號也是同樣的,還有我們之前提到的 reload 和熱升級這樣的過程中都涉及到了優雅的停止 Nginx。
那所謂的優雅的停止 Nginx 究竟是怎樣一個過程呢,接下來讓我一起來學習下吧。
何為優雅的關閉?
所謂的優雅的關閉,是針對 worker 進程而言的,因為只有 worker 進程 才會處理請求。如果我們在處理一個連接的時候,不管連接此時對于請求是怎樣一個作用,直接去關閉鏈接會導致用戶收到錯誤,所以優雅地關閉就是指 Nginx 的 worker 進程 可以識別出當前連接沒有正在處理請求,這個時候再把連接進行關閉。
對于某些請求 Nginx 無法做到優雅地關閉 worker 進程,比如當 Nginx 代理 websocket 協議的時候,在 websocket 后面進行通訊的 frame 楨里面,Nginx 是不解析他的楨的;Nginx 做 TCP 層或者 UDP 層反向代理的時候,也沒有辦法識別一個請求需要經歷多少報文才算是結束;但是對于 HTTP 請求,Nginx 可以做到,所以優雅地關閉主要針對的是 HTTP 請求。
接下來我們去看一下優雅地關閉 worker 進程都有哪些流程。
優雅的關閉流程
首先第一步會設置一個定時器,在 nginx.conf 中可以配置一個 worker_shutdown_timeout,配置完 worker_shutdown_timeout 之后,會加一個標志位,表示進入優雅關閉流程了。
第二步會先關閉監聽句柄,要保證所在的 worker 進程不會再去處理新的連接。
接下來會先去看連接池,因為 Nginx 為了保證對資源的利用是最大化的,經常會保存一些空閑的連接,但是沒有斷開,這時候會首先關閉空閑連接。
第四步是可能非常耗時的一步,因為 Nginx 不是主動的立刻關閉,是通過第一步添加的標志位,然后在循環中每當發現一個請求處理完畢,就會把這個請求使用的連接關掉,所以在循環中等待關閉所有的時間可能會很長。當設置了 worker_shutdown_timeout 的時候,即使請求還沒處理完,當時間到了之后這些請求都會被強制關閉,也就是說優雅地關閉只完成了一半,有一部分連接是立即停止的。
因此在以下兩個條件:當所有循環中連接被優雅地關閉,或者達到了 worker_shutdown_timeout 時間定時器以后,worker 進程都會立即退出。
總結
這篇文章主要講解了 worker 進程優雅關閉的一個過程,很多時候我們都會用到 Nginx 優雅關閉這樣一個特性,那么在這一個特性失效的時候,我們需要考慮 Nginx 有沒有能力去判定一個連接此時應當被正確的關掉;或者說如果出現了錯誤、有些模塊或者有些客戶端不能正常的處理請求時,Nginx 需要有一些例外的措施,比如 worker_shutdown_timeout 來保證 Nginx 老的 worker 進程可以正常的退出掉。
完
