生產環境的一個 connect timeout 故障排查

問題描述

有用戶反饋在dubbo的應用發佈後,過幾分鐘以後,調用方會出現大量的connectTimeout。當時在服務端容器上進行了抓包,看到在故障期間,客戶端發了syn,可是服務端沒有任何響應。

分析問題

正常的TCP三次握手:
  • 客戶端發送syn給服務端發起握手
  • 服務端收到syn後回覆syn+ack
  • 客戶端收到syn+ack後,回覆ack給服務端,此時客戶端上這個鏈接,進入established

從問題描述看,客戶端發的sys包到服務端後直接沒響應了,我初步猜想是syn隊列滿了,經過netstat -s去查看隊列的狀況:
        
1
2
        
3220 times the listen queue of a socket overflowed
3220 SYNs to LISTEN sockets dropped

syn隊列和accept隊列

這裏先解釋下syn隊列和accept隊列:
上圖結合三次握手來講看
  • 客戶端使用connect()向服務端發起鏈接請求(發送syn包),此時客戶端的TCP的狀態爲 SYN_SENT
  • 服務端在收到SYN包後,將TCP相關信息放到 syn隊列中,同時向客戶端發送syn+ack。服務端TCP的狀態爲SYN_RCVD
  • 客戶端收到服務端的syn+ack後,向服務端發送ack,此時客戶端的TCP的狀態爲 ESTABLISHED。服務端收到ack確認後,從 syn隊列裏將 TCP 信息取出,並放到 accept隊列中,此時服務端的TCP的狀態爲 ESTABLISHED
咱們能夠大概瞭解了syn隊列和accept隊列,那再看上面的問題,overflowed表明accept隊列溢出,droped表明syn隊列溢出,發現 3220 SYNs to LISTEN sockets dropped,這個就是表明syn隊列溢出嗎?

overflowed和dropped爲何同樣多

這裏又引出一個問題,能夠看到overflowed和dropped居然同樣多,翻看內核源碼(https://elixir.bootlin.com/linux/v4.14.67/source/net/ipv4/tcp_ipv4.c#L1414)
能夠看到overflow的時候,tcp dropped也會增長,也就是dropped必定大於等於overflowed。這樣看,overflowed和dropped是同樣的,只能說明accept隊列溢出了,而syn隊列溢出爲0(3220-3220)。

進一步分析

可是按照syn隊列和accept隊列的設計,accept隊列滿了應該不影響syn響應,即不影響三次握手。帶着這個疑問咱們再次翻看了 內核源碼:

能夠看到在建連的時候,會判斷accept隊列,若是accept隊列滿了,就會drop,即把這個syn包丟掉了。到這裏,基本上緣由已經查明瞭。

如何優化

按照以前的分析,大概定位到是由於accept隊列滿了,咱們經過ss -lnt查看下:
        
1
2
        
State Recv-Q Send-Q Local Address:Port Peer Address:Port
LISTEN 0 50 *:20990 *:*
上面看到的第二列Send-Q 表示第三列的listen端口上的accept隊列最大爲50,第一列Recv-Q爲accept隊列當前使用了多少。
accept隊列的大小取決於:min(backlog, somaxconn) . backlog是在socket建立的時候傳入的,somaxconn是一個os級別的系統參數。
syn隊列的大小取決於:max(64, /proc/sys/net/ipv4/tcp_max_syn_backlog)。不一樣版本的os會有些差別。
在這個case中,由於用戶的程序發佈拉入後,有大量的客戶端發起請求,從而致使應用的accept隊列滿了,而後致使syn被丟棄。用戶的應用上配置的backlog爲50,因此發現這個現象後,通知研發去更新了dubbo應用的backlog,同時進行發佈驗證,發現問題已經消失了,至此問題解決。

總結

經過文章對故障的分析,你們瞭解了syn隊列和accept隊列的一些知識,同時也瞭解瞭如何去觀測和優化。其實在生產環境中,這種問題比較常見,也很容易被忽視,但願這篇分析對你們有所幫助。
最後引用下阿里童鞋的一句話:
每一個具體問題都是最好學習的機會,光看書理解確定是不夠深入的,請珍惜每一個具體問題,碰到後可以把前因後果弄清楚。

博客原文: https://leeweir.github.io/2019/10/21/一個-connect-timeout-故障排查/
官方資訊*最新技術*獨家解讀

本文分享自微信公衆號 - Go Official Blog(Go_Official_Blog)。
若有侵權,請聯繫 support@oschina.cn 刪除。
本文參與「OSC源創計劃」,歡迎正在閱讀的你也加入,一塊兒分享。linux

相關文章
相關標籤/搜索