1. 問題背景
線上服務變得卡頓,發現 open too many files錯誤,
2. 定位經過
首先查看linux服務器負載是否高,CPU,MEM,磁盤讀寫IOPS(發現高,但是很快排除了,因為是錯誤日志列印太多到本地磁盤)使用netstat 查看當時的連接情況,有條件的可以看監控軟體,發現整體負載不高,事后回顧,如果整體負載不高,那么應該考慮是否有系統設定的限制,
查看linux tcp配置引數, cat/etc/sysctl.conf 或者sysctl -a,發現有人修改了net.ipv4.tcp_max_tw_buckets默認引數,有人把它改小了,當時沒有留意,后面發現才是它是一種錯誤,為啥會把它改小,發現網上有一些人云亦云的博客,說為了提高性能,限制time_wait數量,把數目改小了,所以大家也跟風改,這是正確的嗎?
使用netstat -antp 命令,使用shell awk uniq 去重,統計IP,發現每個IP發現100.xxx.xxx.xx地址的time_wait特別多,而且地址不固定,100開頭的是內部地址,
使用tcpdump命令查看里面的發送內容,發現就是app的介面服務,還有是一些健康檢測的報文,原來是公司使用了阿里云的SLB均衡負載,通過分析報文得知,每次請求,服務都主動關閉了連接,發送FIN,從而產生了time_wait, 所以糾正了我之前的認知,time_wait并不一定是請求方產生的,而是主動關閉連接方產生的,這個通過tcp狀態轉移圖可以看出,
懷疑阿里云SLB均衡負載是不是有問題,在阿里云提交工單,發問有沒有配置可以讓均衡負載IP固定下來,問了好幾次得到答非所問,最后一次技術支持人員才回答到正軌上,回答說不支持,查看檔案,SLB http 7層均衡負載,經過tengine,性能有損耗(相對tcp4層均衡負載),會把長連接轉為短連接,然后檔案說在壓測的情況下會導致后端服務器有大量time_wait.
懷疑代碼框架有問題,但是在本地測驗,發現正常,都是客戶端主動發起斷開請求,服務端沒有產生time_wait,通過tcpdump獲取報文,與線上的發出報文對比,發現線上的請求方http header 帶有connect:close, 本地測驗加上了header,問題就復現了,
換個代碼框架測,使用python flask,發現不能復現,通過tcpdump報文分析,發現flask默認使用http 1.0協議進行應答,使用http 1.1 需要設定,設定完畢后,python flask框架也能復現了,所以,每個框架實作http,而http是一種協議,所以成熟的框架在http請求里面的表現都應該是一致的,
懷疑是客戶端請求有問題,讓客戶端請求頭 加上keep-alive: timeout=3,max=1 , 經過測驗,3s超時后并沒有關閉,后面看文章,發現客戶端的超時設定只是一種沒有約束力的通知,最終由服務端來決定超時時間,
后面通過排查,客戶端的同事說請求沒有帶上connect:close 的頭,但是線上tcpdump看有這個頭,懷疑是其他地方加上的,并通過發工單給阿里云,確認了connect:close是SLB均衡負載產品主動給請求加上的,以達到實作變成短連接的目的,這個也是http 1.1協議的定義,http1.1默認使用長連接,要帶上這個引數來關閉長連接,
如果長連接的話,服務端可以復用連接,不用每次三次握手,如果是客戶端主動關閉的話,服務端不會產生time_wait,但是會產生close_wait,而通過tcp狀態轉移圖,close_wait在對端發回應答,即可馬上回收(后續描述又是一個問題),而time_wait需要等待2MSL,這個時間比較久(這個沒有按照RFC協議規定時間,一般幾分鐘左右),回收連接比較慢,會造成堆積,
但是目前系統負載不高,time_wait數量不多,所以盡管time_wait產生堆積,也不足以產生性能問題,反復排查,time_wait數量很固定,與想tcp_max_tw_buckets這引數閾值很接近,懷疑是設定的問題,通過查看官方說法:
This limit exists only to prevent simple DoS attacks, you _must_ not lower the limit artificially,but rather increase it (probably, after increasing installed memory),if network conditions require more than default value.
所以網上的那些優化性能的文章,誤導了很多人,不應該隨便調tcp的引數,把tcp_max_tw_buckets恢復默認值,后續觀察得到緩解,
但是open too many files的問題,還是時不時出現,這個導致服務阻塞,所以后續文章分析一下close_wait的問題,其中再分析一下tcp連接連接,釋放連接程序中遇到的問題,
轉載請註明出處,本文鏈接:https://www.uj5u.com/caozuo/216788.html
標籤:Linux
上一篇:分公司域控問題,請高手指點!
下一篇:tcp協議在定位中的應用
