服務器tcp連接timewait過多優化及詳細分析

【背景說明】

在7層負載均衡上,查詢網絡狀態發現timewait太多,於是開始準備優化事宜

整體的拓撲結構,前面是lvs做dr模式的4層負載均衡,後端使用(nginx、or haproxy)做7層負載均衡

【優化效果】

修改前,建立連接的有29個,timewait的就達到了900個,如下圖所示

wKiom1Ty5IfhAB9FAAEI5rK5xCU064.jpg

修改後,建立連接的有32個,timewait的從900降低到了49個,如下圖所示

wKioL1Ty5aOCeWn5AAEKHpcJW_c047.jpg


【具體優化方案】

注意:前端使用nat時,不適用本策略。詳細“方案詳細介紹”會說明

修改7層負載所在機器,/etc/sysctl.conf

net.ipv4.tcp_tw_reuse = 1

net.ipv4.tcp_tw_recycle = 1

net.ipv4.tcp_timestamps = 1

net.ipv4.tcp_fin_timeout = 20

保存後sysctl -p生效


【方案詳細介紹】

1
net.ipv4.tcp_tw_reuse = 1

#表示開啓重用。允許將TIME-WAIT sockets重新用於新的TCP連接,默認爲0,表示關閉;該文件表示是否允許重新應用處於TIME-WAIT狀態的socket用於新的TCP連接(這個對快速重啓動某些服務,而啓動後提示端口已經被使用的情形非常有幫助)


1
net.ipv4.tcp_tw_recycle = 1


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


net.ipv4.tcp_timestamps 開啓時,net.ipv4.tcp_tw_recycle開啓才能生效,原因可以參考以下代碼

12345678    if (tcp_death_row.sysctl_tw_recycle && tp->rx_opt.ts_recent_stamp)             recycle_ok = icsk->icsk_af_ops->remember_stamp(sk);
if (recycle_ok) {    
                         tw->tw_timeout = rto;     
                                             }
else {          tw->tw_timeout = TCP_TIMEWAIT_LEN;
if (state == TCP_TIME_WAIT)                                     
timeo = TCP_TIMEWAIT_LEN;
 }


如 果服務器身處NAT環境,安全起見,通常要禁止tcp_tw_recycle,如果nat下,開啓了tcp_tw_recycle,可能會導致部分用戶無 法連接服務器的情況:在nat模式下(服務器一般會用到dnat,用戶一般會用到snat),nat設備(or服務器)會修改目的ip和源ip,以屏蔽內 部信息。試想很多用戶snat出來,通過dnat訪問網站,在dnat這層,時而會產生時間戳錯亂的問題,那麼基於tcp的時間戳的tcp_tw_recycle,就會出錯。具體可參考

fc1323的擴展的說明

 RFC 1323          TCP Extensions for High Performance           May 1992


           discarded when a connection is closed.

           An additional mechanism could be added to the TCP, a per-host
           cache of the last timestamp received from any connection.
           This value could then be used in the PAWS mechanism to reject
           old duplicate segments from earlier incarnations of the
           connection, if the timestamp clock can be guaranteed to have
           ticked at least once since the old connection was open.  This
           would require that the TIME-WAIT delay plus the RTT together
           must be at least one tick of the sender's timestamp clock.
           Such an extension is not part of the proposal of this RFC.

           Note that this is a variant on the mechanism proposed by
           Garlick, Rom, and Postel [Garlick77], which required each
           host to maintain connection records containing the highest
           sequence numbers on every connection.  Using timestamps
           instead, it is only necessary to keep one quantity per remote
           host, regardless of the number of simultaneous connections to
           that host.

大致意思爲:tcp會記錄每個連接的時間戳,如果後續時間戳比之前記錄的時間戳小,就會認爲這是錯誤的連接,拒絕這個連接。如果tcp_tw_recycle開啓,那麼這種規則就會被激活(那樣才能快速回收連接)。所以在lvs使用nat的情況下,用 戶請求到lvs,LVS會修改地址數據後將請求轉發給後端服務器,但不會修改時間戳(因爲nat的機制就是隻修改源地址和目的地址)。在後端服務器看來, 請求的源地址永遠都是LVS的地址,並且端口複用,原本不同客戶端的請求經過LVS的轉發,就可能會被認爲是同一個連接,加之不同客戶端的時間可能不一 致,所以就會出現時間戳錯亂的現象,於是後面的數據包就被丟棄了,具體的表現通常是是客戶端明明發送的SYN,但服務端就是不響應ACK,還可以通過下面 命令來確認數據包不斷被丟棄的現象。就會出現部分用戶能連接服務器,部分用戶不能連接服務器的情況。


但在LVS使用用dr模式情況下,lvs只會修改mac和ip地址的映射關係,後端服務器看到的還是不通的用戶ip,所以激活這一規則,也不會有問題。我們這裏能使用這個策略,最大的原因也是在這裏

1
net.ipv4.tcp_timestamps = 1

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


net.ipv4.tcp_fin_timeout = 15;這個參數是用來設置保持在FIN_WAIT_2狀態的時間。tcp4此揮手,正 常的處理流程就是在FIN_WAIT_2情況下接收到FIN進入到TIME_WAIT的情況,tcp_fin_timeout參數對處於 TIME_WAIT狀態的時間沒有任何影響。但是如果這個參數設的比較小,會縮短從FIN_WAIT_2到TIME_WAIT的時間,從而使連接更早地進 入TIME_WAIT狀態。狀態開始的早,等待相同的時間,結束的也早,客觀上也加速了TIME_WAIT狀態套接字的清理速度。 

tcp連接的斷開,可參考以下狀態機:

wKiom1Ty5LmjaqrnAAHQ0NimpRk554.jpg


【補充說明】

如果變更後運行命令netstat -s|grep timestamp

發現packets rejects in established connections because of timestamp

數值增加的很快,你可能得回滾這個變更了:說明使用snat訪問你網站的人很多


因 爲:雖然服務器端沒有使用nat,但是客戶端使用snat的情況很多,如果後發現packets rejects in established connections because of timestamp增長很快,建議將這個方案回滾。那時,可使用修改net.ipv4.tcp_max_tw_buckets(centos默認似乎是 262144)可調整至100000。其實也說明,timeout數量不大的時候,其實可以不用調整tcp_tw_recycle參數(風險很大)。

wKiom1Ty5J6j_VO0AACyl62w9hk303.jpg


【總結】

一個小小的變更,背後涉及的知識是異常多的,所以需要

     1、不能隨意找個方案就使用,需要深入理解。就像說這個A藥可以治療B症狀,但是本質是A藥可以治療C病因情況下得B症狀,需要把病因搞清楚了再吃藥。就算僥倖治療好了,也不能永遠都是報這種僥倖心理。

     2、對於內核參數調整,需要對每個參數都瞭解之後再行動,否則可能會有悲劇。

     3、變更的時候,需要有一個灰度過程,需要觀察一段時間後,再大面積修改。


本文出自 “H2O's運維&開發路” 博客,轉載請與作者聯繫


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