Time_wait問題小結


轉載自: http://mp.weixin.qq.com/s?__biz=MzAxOTg2NDUyOA==&mid=2657554876&idx=1&sn=05990e85c366e45415d77593b0d3bda1&mpshare=1&scene=1&srcid=0928LA06I6JCzy2vKKkaPt9f#rd

 

                        Time_wait問題小結                    

2016-09-28 測試那點事兒 測試那點事兒

TIME_WAIT的產生原因

因為TCP連接是雙向的,所以在關閉連接的時候,兩個方向各自都需要關閉。先發FIN包的一方執行的是主動關閉;后發FIN包的一方執行的是被動關閉。主動關閉的一方會進入TIME_WAIT狀態,並且在此狀態停留兩倍的MSL時長。

MSL指的是報文段的最大生存時間,如果報文段在網絡活動了MSL時間,還沒有被接收,那么會被丟棄。關於MSL的大小,RFC 793協議中給出的建議是兩分鍾,不過實際上不同的操作系統可能有不同的設置,以Linux為例,通常是半分鍾,兩倍的MSL就是一分鍾,也就是60秒,並且這個數值是硬編碼在內核中的,也就是說除非你重新編譯內核,否則沒法修改它。

TIME_WAIT狀態存在的必要性。為什么主動關閉的一端不直接進入closed狀態,而是要先進入time_wait並且停留兩倍的MSL時長呢?這是因為TCP是建立在不可靠網絡上的可靠協議。如果主動關閉的一端收到被動關閉一端的發出的FIN包后,返回ACK包,同時進入TIME_WAIT,但是由於網絡的原因,主動關閉一端發送的ACK包可能會延遲,從而觸發被動關閉一方重傳FIN包,這樣一來一回極端情況正好是2MSL。如果主動關閉的一端直接close或者不到兩倍MSL時間就關閉,那么被動關閉發出重傳FIN包到達,可能出現的問題是:舊的連接不存在,系統只能返回RST包;新的TCP連接已經建立,延遲包可能會干擾新連接。這都可能導致TCP不可靠。

TIME_WAIT過多的危害

在生產過程中,如果服務器使用短連接,那么完成一次請求后會主動斷開連接,就會造成大量time_wait狀態。因此我們常常在系統中會采用長連接,減少建立連接的消耗,同時也減少TIME_WAIT的產生,但實際上即使使用長連接配置不當時,當TIME_WAIT的生產速度遠大於其消耗速度時,系統仍然會累計大量的TIME_WAIT狀態的連接。TIME_WAIT狀態連接過多就會造成一些問題。如果客戶端的TIME_WAIT連接過多,同時它還在不斷產生,將會導致客戶端端口耗盡,新的端口分配不出來,出現錯誤。如果服務器端的TIME_WAIT連接過多,可能會導致客戶端的請求連接失敗,這在接下來舉例說明。

請TIME_WAIT問題定位

案例一: 將nginx作為反向代理時,后連tomcat等服務器。測試中不同並發壓力下多次、反復出現nginx服務器端口資源耗盡的問題。表現為nginx服務器出現大量time_wait狀態連接,端口資源耗盡(nginx報錯:cannot assign requested address )。首先檢查nginx開啟了長連接keepalive,但是系統仍然出現了大量的TIME_WAIT,這就和之前提到的當系統產生TIME_WAIT的速度大於其消耗速度時,就會累計TIME_WAIT。原因是:keepalive取配置太小,將其增大后問題得以解決。(PS:nginx總的keepalive連接池大小 = keepalive取值 * nginx worker數)

案例二:

某應用其中一層系統架構Nginx+Tomcat,客戶端發出的請求為HTTP HEAD,客戶端TPS有段時間接近為0,返回Connection time out錯誤。

觀察大部分錯誤請求響應時間剛好是30s,這正好是nginx的連接超時時間配置,Tomcat沒有收到這些錯誤請求,這意味着請求Nginx連接Tomcat都沒有成功。這是為什么呢?Tomcat的連接池不夠用嗎? 實際上Tomcat work線程不到200個,遠小於MaxThread(1024)的值,同時還觀察到Tomcat上的TIME_WAIT連接數量不正常,達到了近兩萬個。

系統是設置了長連接的,為什么還有這么多TIME_WAIT,難道長連接沒有生效嗎?

         Nginx作為反向代理,長連接配置主要有三項,upstream中的keepalive設置單個worker最大請求數,參數proxy_http_version  1.1強制轉換為http1.1協議(默認支持長連接),proxy_set_header Connection將請求頭部connection為空(http1.0請求默認connection頭部為close)

upstream backend_nosfs {

       server 10.10.10.10:8185;

       keepalive 1024;

       #keepalive_requests;

   }

proxy_http_version 1.1;

proxy_set_header Connection "";

         Tomcat端增加配置maxKeepAliveRequests=“10000”,表示一個連接上最大請求數達到10000才會斷開。

    定位長連接問題,最簡單直接的方法就是抓包,通過wireshark分析Nginx和Tomcat直接連接果然沒有生效,一條連接只處理了一個請求。

為什么設置了長連接相關的配置,還是沒有生效呢?經過排查發現,proxy_http_version 1.1;

proxy_set_header Connection ""這兩項配置放在Nginx的Http域中,實際上他們要放在server域才會生效,將其位置修改后,長連接生效了,所有問題都解決了。但是我們不禁會嘗試疑問TIME_WAIT出現在Tomcat而不是在Nginx上?從抓包可以看出Nginx發送給Tomcat包頭部Connection為close,所以Tomcat在處理完head請求后就主動關閉,所以TIME_WAIT出現在Tomcat服務器。 配置修改后,問題解決了,TPS也上去了,之前出現的連接失敗問題也沒有了。

     但是為什么Tomcat服務器上的TIME_WAIT過多會導致Nginx連接失敗呢?理論上說,服務器只監聽在一個端口,但是會new出很多socket去處理請求,難道是socket不夠用嗎?再觀察資源使用發現雖然TIME_WAIT連接數多,但是句柄數並不多,而socket的數量是受制於句柄數。那真正的原因是什么呢?在系統TIME_WAIT較多時,Dmesg系統出錯日志為:

nf_conntrack: table full, dropping packet

      真相大白了,Conntrack表用於記錄每個連接的狀態,在tcp協議中用源ip/port+目的ip/port唯一標識一個連接。記錄TCP連接狀態的表滿了導致請求失敗。查看系統ip_contrack_max配置為

65536,在極端的情況下超出了其配置所有導致連接失敗。

如何控制TIME_WAIT數量

通過以上的TIME_WAIT問題,我們可以看到TIME_WAIT這個狀態不存在不行,但是過多就對系統會造成困擾。那么我們應該如何控制TIME_WAIT的數量呢?

長連接

對於反向代理和應用服務器,最好是要配置成支持keepalive長連接,否則在系統並發增加時會導致一系列的連接問題。對於nginx+tomcat長連接的配置前面有一些介紹可以參考,其它服務器一般也是提供支持長連接配置的,設置后建議抓包測試驗證。

一般來說長連接設置正確了TIME_WAIT數量不會暴漲,但是長連接最大請求數也是有效的,但如果應用的處理速度很快導致TIME_WAIT的產生的速度遠快於TIME_WAIT的消耗速度時系統就會累計TIME_WAIT狀態連接。這時候可能就要修改一些系統配置了。

ip_conntrack

用於跟蹤TCP連接。一旦激活了此模塊,就能在系統參數里發現很多用來控制網絡連接狀態超時的設置,其中自然也包括TIME_WAIT,默認ip_conntrack_max最大為65536,可以將其設置得更大一些。一般不建議此模塊,如果系統安裝使用iptable會啟動該模塊。

tcp_tw_recycle

在網上搜索TIME_WAIT問題的解決方法,大多都會提到這個參數,不過官方網站上不建議開啟這個參數,原因是會導致一些安全問題。例如,當多個客戶端通過NAT方式聯網並與服務端交互時,服務端看到的是同一個IP,由於這些客戶端的時間戳可能存在差異,所以從服務端的視角看,便可能出現時間戳錯亂的現象,進而直接導致時間戳小的數據包被丟棄。

tcp_tw_reuse

當創建新連接的時候,如果可能的話會考慮復用相應的TIME_WAIT連接。官方文檔里提到的是如果從協議視角看它是安全的,那么就可以使用。這個很難判定這個參數是否應該開啟,不到萬不得已的時候,即使我們要開啟這個參數復用連接,也應該在連接的發起方使用,而不能在被連接方使用。

tcp_max_tw_buckets

用於控制TIME_WAIT總數。這個選項是為了阻止一些簡單的DoS攻擊,平常不要人為的降低它。如果TIME_WAIT已經成為最棘手的問題,那么即便此時並不是DoS攻擊的場景,也可以嘗試通過設置它來減少TIME_WAIT數量。

安大叔說

生活最沉重的負擔不是工作和房價,而是無聊,無所事事,沒有追求,沒有方向,沒有目標,那么請給自己找點事做吧

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM