記一次服務器timewait事件

之前一直沒怎麼關注過TCP,直到公司這次的事件,這纔開始慢慢去研究,去學習TCP的相關知識,中間也嘗試了很多方法,走了很多彎路,因此記下這篇文章,方便以後回顧


首先說下網絡架構

wKioL1er6pXQqOp6AAGP92QX2TQ170.png-wh_50


Nginx和jetty都在同一個服務器,Nginx代理HTTP流量至多個jetty應用,基本情況就是這樣


首先我們來看下,爲什麼會有TIMEWAIT的狀態

734c7efd-3d62-3946-a234-acdddff3b507.jpg

客戶端主動關閉連接時,會發送最後一個ack後,然後會進入TIME_WAIT狀態,再停留2個MSL時間,進入CLOSED狀態。

也就是說一般timewait只會出現在client中(因爲主動關閉),server端是不會關閉連接的(以爲一直在監聽)


基於此,我查看了服務器的情況

發現nginx對外的tcp連接數狀態是正常的,問題就在對於jetty的連接數異常的多,並且不釋放


首先度娘解決方法,基本得到的結果基本就是一個修改內核參數(不推薦此做法)

net.ipv4.tcp_tw_reuse = 1 

#表示開啓重用。允許將TIME-WAIT sockets重新用於新的TCP連接,默認爲0,表示關閉 

net.ipv4.tcp_tw_recycle = 1

#表示開啓TCP連接中TIME-WAIT sockets的快速回收,默認爲0,表示關閉  

這樣是可以快速的的回收socket,但是後來查詢資料發現這樣做有隱患

1.對於net.ipv4.tcp_tw_recycle ,Linux內核文檔中實戰和麼描述的

tcp_tw_recycle (Boolean; default: disabled; since Linux 2.4)[譯者注:來自linux man tcp的描述]

Enable fast recycling of TIME-WAIT sockets. Enabling this option is not recommended since this causes

problems when working with NAT (Network Address Translation).

啓用TIME-WAIT狀態sockets的快速回收,這個選項不推薦啓用。在NAT(Network Address Translation)網絡下,會導致大量的TCP連接建立錯誤。

2.有些文檔中也說了對於手機端wifi訪問的話,也會有問題,因爲wifi端訪問時間戳會亂跳,導致訪問拒絕

基於以上2個隱患,所以沒有使用此方法。


後來我再觀察的時候,我發現nginx和jetty之間的連接大多都是短連接(因爲默認nginx也是使用短連接),所以有可能是nginx作爲client會快速釋放,所以導致nginx的socket一直都是出於timewait狀態,所以去nginx官網查看資料,配置nginx在負載均衡的時候使用長連接


具體配置爲:

upstream localhost{          

……

keepalive 30;

  }

location / {

               ……           

            proxy_http_version 1.1;

            proxy_set_header Connection "";

        }

在server 的location模塊裏面 添加以上信息。

    注意:需要設置nginx 代理請求的 http 協議版本號爲 1.1,  以及清除掉 Connection 請求header

官方文檔描述:

For HTTP, the proxy_http_version directive should be set to “ 1.1 ”  and the  “Connection ”  header field should be cleared 

因爲http協議1.1默認就使用長連接,所以不需要Connection的頭部信息,這樣打開nginx和jetty之間的長連接之後,timewait的狀態大量減少。


總結:我們在遇到問題的時候,百度遇到的解決方案一定要仔細分析,千萬不能隨隨便便就使用,因爲別人的環境跟你的有可能不一樣,即便當時能夠解決問題,後面引發的問題,可能更加難以發現和解決。

還有我們遇到問題要多想,千萬不能自以爲是什麼什麼原因,要有事實依據,才能找到更好的解決方案

最後歡迎大家一起交流和學習。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章