問題描述:
最近遇到了一個syn丢包的情況,當系統磁盤、網絡、cpu都無壓力的時候,系統莫名其妙出現“sync to listen sockets drop”問題;無論帶寬是10M還是8G,都會出現這種這種情況。現象為:輸入系統指令:netstat -s | grep LISTEN,會出現 syns to listen sockets dropped; 但是并沒有times the listen queue of a socket overflowed;連接配接隊列包括兩種,一個是半連接配接隊列(syn queue),一個是全連接配接隊列(accept queue);根據上述描述,accept隊列并沒有溢出,而syn隊報丢失有可能是syn隊列溢出的原因,也可能是其他原因;"syns to listen sockets dropped"意思是:收到三次握手的ack包,因為各種原因導緻建立socket的過程中被丢棄;
首先我們分析了一下netstat -s裡面的資料,發現"passive connections rejected because of time stamp"的值和"syns to listen sockets dropped"相差不大,很多伺服器他們的值都是相同的,這個讓人感覺sync to listen sockets drop的原因有可能與時間戳有關;

我們檢查了一下系統的配置:
or的keepalive設定為512個,總共40個cpu;系統級别的監聽隊列長度是65535,syn隊列是26w;or的每個程序監聽隊列是20w;
我們的架構是上層是openresty,下層是我們的自研緩存軟體;
syns to listen sockets dropped; 是由于在三次握手過程中建立socket失敗,但是我們不知道是or或者cache軟體作為用戶端丢失syn包還是or或者cache軟體作為伺服器丢失syn包;于是我們做了一系列測試;
發現以下幾點:
1. client(使用者)通路or層,會導緻or層作為伺服器端的syn包丢失;
2. or作為用戶端,通路cache軟體時,or發出的syn包沒有丢失;(or和cache軟體是同一個機房);
3. cache軟體作為伺服器,接受到的syn包沒有丢失;
4. cache軟體作為用戶端,發出去的syn包沒有丢失(cache軟體主要是給其他IDC發送http請求);
于是我們的重點是解決使用者給or的syn包丢失的問題;
我們從網上查找原因,查到了最有可能的原因:
:因為2.6核心以上中tcp_timestamps預設是打開的,是以當打開 tcp_tw_recycle時會導緻部分通過NAT上網client無法正确連接配接伺服器,故障表現為client發出SYN後無法收到server傳回 的SYN+ACK,推薦的解決方法是關閉tcp_tw_recycle,打開tcp_tw_reuse解決TIME-WAIT過多的問題。
我們将/proc/sys/net/ipv4/tcp_tw_recycle修改為0,drop情況就不發生了;
然後檢視tw個數:
netstat -n | awk '/^tcp/ {++S[$NF]} END {for(a in S) print a, S[a]}'
下面我們總結一下:
tcp_tw_recycle 設定為 1 會開啟系統對 TIME_WAIT 狀态的 socket 的快速回收。開啟這個功能,系統就會存下 TCP 連接配接的時間戳,當同一個 IP 位址過來的包的時間戳小于緩存的時間戳,系統就直接丢包,“回收”這個 socket。這個選項同樣需要開啟 tcp_timestamp 才生效。
開啟這個功能是有很大風險的,伺服器端會根據同一個 IP 發送過來的包的時間戳來判斷是否丢包,而時間戳是根據發包的用戶端的系統時間得來的,如果服務端收到的包是同一出口 IP 而系統時間不一樣的兩個用戶端的包,就有可能會丢包,可能出現的情況就是一個區域網路内有的用戶端能連接配接服務端,有的不能。具體原因是用戶端處于NAT模式下,出口ip可能是同一個ip,不同用戶端的發送的時間戳可能亂序,伺服器會檢查相同ip位址發送來過的包的時間戳是不是小于緩存的時間戳,如果不是,直接丢掉;
有可能drop package的情況:(伺服器端tcp_tw_recycle和tcp_timestamp都開啟)
1.lvs處于NAT模式(咱們是DR);
2.用戶端處于NAT模式;
3.IDC處于NAT模式;有人對國内的節點做了一個可視化分析,發現有2.61%的機率出口存在NAT的這種情況;
在伺服器上最好打開tcp_tw_reuse,并且關閉tcp_tw_recycle。
tcp_tw_reuse和tcp_tw_recycle差別:
1. tw_reuse,tw_recycle 必須在用戶端和服務端timestamps 開啟時才管用(預設打開)
2. tw_reuse 隻對用戶端起作用,開啟後用戶端在1s内回收
3. tw_recycle 對用戶端和伺服器同時起作用,開啟後在 3.5*RTO 内回收,RTO 200ms~ 120s 具體時間視網絡狀況。内網狀況比tw_reuse 稍快,公網尤其移動網絡大多要比tw_reuse 慢,優點就是能夠回收服務端的TIME_WAIT數量;