什么是lingering_close?
lingering_close是延遲關閉,當Nginx要關閉連接時,並非立即關閉連接,而是先關閉tcp連接的寫,再等待一段時間后在關閉連接的讀。
為什么要有lingering_close?
Nginx在接收客戶端請求的時候,如果客戶端或服務端出錯,Nginx要立即響應錯誤信息給客戶端,在它響應錯誤信息后,大部分情況下需要關閉當前連接。
Nginx執行完write()系統調用把錯誤信息發送給客戶端,write()系統調用返回成功不代表數據已經發送到客戶端,有可能還在tcp連接的write buffer里,如果直接執行close()系統調用關閉tcp連接,內核會先檢查tcp的read buffer里有沒有客戶端發過來的數據留在內核態沒有被用戶態進程讀取。如果有則發送客戶端RST報文(Reset the connection用於復位因某種原因引起出現的錯誤連接,也用來拒絕非法數據和請求)來關閉tcp連接丟棄write buffer里的數據,,如果沒有則等待write_buffer的數據發送完畢后再4次揮手報文斷開連接。
由上可知,如果write buffer里的數據在write() 系統調用后到close()系統調用前沒有發送完畢,且read buffer里有數據沒有讀,就會導致客戶端收到RST報文且不會拿到服務端發送的錯誤信息。這個場景是因為服務端給客戶端發送了RST報文導致自己發送的數據在客戶端被忽略了。
解決方案如下,我們關掉tcp連接的寫,讀正常進行,此時客戶端再發數據來,就不會受到RST。Nginx還會設置一個超時時間lingering_timeout,超過這個時間內還沒有收到數據則關掉連接,而正常的客戶端在讀取到數據后也會關掉連接。
lingering_time
Nginx中設置的連接的總的讀取時間,就是通過lingering_time來設置,這個時間也是Nginx關閉寫之后保留socket的時間,客戶端需要在這個時間內發送完所有數據,否則Nginx在這個時間后會直接關掉連接。
lingering_close的優缺點
可以保持更好的客戶端兼容性,但是會消耗更多的額外資源(比如連接會一直占着)。
以上總結參考鏈接https://mp.weixin.qq.com/s/bXtI45d7M-XjkJH3ARZiMQ