以前咱們講解 Nginx 命令行的時候,能夠看到 Nginx 中止有兩種方式,分別是 nginx -s quit
和 nginx -s stop
,其中 stop 是指當即中止 Nginx,而 quit 是指優雅的關閉 Nginx,對應的信號也是一樣的,還有咱們以前提到的 reload 和熱升級這樣的過程當中都涉及到了優雅的中止 Nginx。nginx
那所謂的優雅的中止 Nginx 到底是怎樣一個過程呢,接下來讓我一塊兒來學習下吧。web
所謂的優雅的關閉,是針對 worker 進程而言的,由於只有 worker 進程 纔會處理請求。若是咱們在處理一個鏈接的時候,無論鏈接此時對於請求是怎樣一個做用,直接去關閉連接會致使用戶收到錯誤,因此優雅地關閉就是指 Nginx 的 worker 進程 能夠識別出當前鏈接沒有正在處理請求,這個時候再把鏈接進行關閉。websocket
對於某些請求 Nginx 沒法作到優雅地關閉 worker 進程,好比當 Nginx 代理 websocket 協議的時候,在 websocket 後面進行通信的 frame 楨裏面,Nginx 是不解析他的楨的;Nginx 作 TCP 層或者 UDP 層反向代理的時候,也沒有辦法識別一個請求須要經歷多少報文才算是結束;可是對於 HTTP 請求,Nginx 能夠作到,因此優雅地關閉主要針對的是 HTTP 請求。socket
接下來咱們去看一下優雅地關閉 worker 進程都有哪些流程。學習
首先第一步會設置一個定時器,在 nginx.conf 中能夠配置一個 worker_shutdown_timeout,配置完 worker_shutdown_timeout 以後,會加一個標誌位,表示進入優雅關閉流程了。ui
第二步會先關閉監聽句柄,要保證所在的 worker 進程不會再去處理新的鏈接。命令行
接下來會先去看鏈接池,由於 Nginx 爲了保證對資源的利用是最大化的,常常會保存一些空閒的鏈接,可是沒有斷開,這時候會首先關閉空閒鏈接。代理
第四步是可能很是耗時的一步,由於 Nginx 不是主動的馬上關閉,是經過第一步添加的標誌位,而後在循環中每當發現一個請求處理完畢,就會把這個請求使用的鏈接關掉,因此在循環中等待關閉全部的時間可能會很長。當設置了 worker_shutdown_timeout 的時候,即便請求還沒處理完,當時間到了以後這些請求都會被強制關閉,也就是說優雅地關閉只完成了一半,有一部分鏈接是當即中止的。code
所以在如下兩個條件:當全部循環中鏈接被優雅地關閉,或者達到了 worker_shutdown_timeout 時間定時器之後,worker 進程都會當即退出。blog
這篇文章主要講解了 worker 進程優雅關閉的一個過程,不少時候咱們都會用到 Nginx 優雅關閉這樣一個特性,那麼在這一個特性失效的時候,咱們須要考慮 Nginx 有沒有能力去斷定一個鏈接此時應當被正確的關掉;或者說若是出現了錯誤、有些模塊或者有些客戶端不能正常的處理請求時,Nginx 須要有一些例外的措施,好比 worker_shutdown_timeout 來保證 Nginx 老的 worker 進程能夠正常的退出掉。