你們是否也遇到過這些情況:客戶端無法連接到伺服器、連接異常斷開、連接狀態不正確(TIMEWAIT狀態SOCK過多)。遇到這些情況,要怎麼找出背後真正的故障原因呢?

例如網路不互通、伺服器負載過高無法處理新連接、backlog相關連接隊列滿等等,都是造成這些情況的原因。今天Test+團隊來詳細講解一下如何使用netstat排查網路問題。

一、抓包能解決什麼問題

客戶端與伺服器網路連接異常的問題

客戶端調用connect連接伺服器,在程序中進入異常流程,即連接失敗。此時可以通過抓包工具來分析是客戶端還是伺服器的問題。連接建立階段的抓包交互為:

11:30:27.998097 IP GZ-6CU4172K6K.44775 > 10.20.102.232.http: Flags [S], seq 44374208, win 14600, options [mss 1460,sackOK,TS val 2511054656 ecr 0,nop,wscale 7], length 0 11:30:27.998351 IP 10.20.102.232.http > GZ-6CU4172K6K.44775: Flags [S.], seq 2839180825, ack 44374209, win 28960, options [mss 1460,sackOK,TS val 2490824937 ecr 2511054656,nop,wscale 7], length 0 11:30:27.998400 IP GZ-6CU4172K6K.44775 > 10.20.102.232.http: Flags [.], ack 1, win 115, options [nop,nop,TS val 2511054656 ecr 2490824937], length 0

三次握手的包,在tcpdump中表現是[S] (wireshark中位SYN),如果出現上述三個報文,表明客戶端與伺服器正常建立了連接。如果未抓到包,表明客戶端根本未發起連接;如果伺服器未回復[S.]報文,表明伺服器未響應連接,此時可能就是伺服器存在BUG或者性能瓶頸了。

客戶端與伺服器網路連接異常斷開的問題

客戶端在運行過程中,開始一段時間表現良好,但一段時間後,連接就異常斷開了,通過日誌排查只能得到部分錯誤碼,但無法完全確定究竟是網路問題還是其它問題,此時我們通過持續抓包也可以確認到問題。正常的網路連接與斷開包序如下:

11:30:27.998097 IP GZ-6CU4172K6K.44775 > 10.20.102.232.http: Flags [S], seq 44374208, win 14600, options [mss 1460,sackOK,TS val 2511054656 ecr 0,nop,wscale 7], length 011:30:27.998351 IP 10.20.102.232.http > GZ-6CU4172K6K.44775: Flags [S.], seq 2839180825, ack 44374209, win 28960, options [mss 1460,sackOK,TS val 2490824937 ecr 2511054656,nop,wscale 7], length 011:30:27.998400 IP GZ-6CU4172K6K.44775 > 10.20.102.232.http: Flags [.], ack 1, win 115, options [nop,nop,TS val 2511054656 ecr 2490824937], length 011:31:28.060018 IP 10.20.102.232.http > GZ-6CU4172K6K.44775: Flags [F.], seq 1, ack 1, win 227, options [nop,nop,TS val 2490884998 ecr 2511054656], length 011:31:28.060160 IP GZ-6CU4172K6K.44775 > 10.20.102.232.http: Flags [F.], seq 1, ack 2, win 115, options [nop,nop,TS val 2511114718 ecr 2490884998], length 011:31:28.060358 IP 10.20.102.232.http > GZ-6CU4172K6K.44775: Flags [.], ack 2, win 227, options [nop,nop,TS val 2490884998 ecr 2511114718], length 0

[F]報文是關閉連接時的報文,wireshark中對應的為[FIN],某個端先發起[F]報文,則是該端主動發起連接關閉操作。

如果對於異常斷開連接,抓取到的報文為客戶端發起的,那可能客戶端某個邏輯存在關閉連接的可能,否則,就是伺服器主動關閉連接,則可以進一步分析伺服器問題。一般來說伺服器關閉連接有幾種可能:長時間無數據空閑連接回收機制、收到無法處理的數據包認為其連接非法進行關閉、伺服器關閉等等情形。

除了正常關閉[F]報文,還存在一種情形來重置TCP連接,那就是[R]報文,在wireshark中使用[RST]報文標識。某些伺服器主動關閉連接時,為了避免tcp進入TIME_WAIT狀態,會設置linger選項,讓連接關閉時也取消發送緩衝區的數據,此時就會發送一個[R]報文直接中斷連接,客戶端在recv時就會返回-1(正常關閉recv返回0),同時存在一個10053的錯誤碼(windows)。這種情形出現時並非是伺服器存在問題,還是伺服器有意為之(確實存在部分伺服器使用這種邏輯)。

[R]報文出現時,可以深究其原因,下面列出幾種可能出現[R]報文的原因:

?目標埠未打開;

?關閉socket時,socket系統層接收緩衝區中存在部分數據未收取;

?部分系統(如windows 2003)在重傳多次失敗後會發送[R]報文;

?伺服器設置socket的linger選項;

通過抓包觀察伺服器客戶端狀態

抓包除了分析單個TCP連接的轉換之外,還可以分析伺服器或客戶端的運行時狀態。抓包可以觀察win(窗口大小),如果伺服器回復的報文中win存在下降趨勢,並在某一時刻收到伺服器的zero window標識的報文,說明伺服器存在性能瓶頸,無法及時響應客戶端的請求,抑或者整個系統的設計存在缺陷,客戶端不應以較快速度向伺服器發包。

通過觀察網路包重傳,也可以分析到客戶端與伺服器的網路通暢程度。

二、包與連接狀態查看相結合

在伺服器中通過netstat -na 查看連接狀態

在伺服器中通過netstat -na查看連接狀態,可以看到連接正常、連接斷開、TIME_WAIT等等可能狀態的TCP連接,若一個系統出現了大量TIME_WAIT狀態的連接,說明該伺服器經常主動發起連接關閉操作,這也是不可取的。如一個系統頻繁出現CLOSE_WAIT狀態的連接,說明該系統並未立即處理連接關閉請求,系統也存在缺陷。

同時通過觀察netstat -na的send-q和recv-q隊列的大小,可以分析系統服務能力,若send-q過大,說明系統發包速度過快以至於連接無法及時將數據發出。若recv-q過大,說明系統未能及時處理外部發來的請求。

通過netstat還可以檢測伺服器是否能正常處理客戶端連接。伺服器在調用listen時,會傳遞backlog參數,該參數未已建立連接但未被程序accept的連接數,內核層會根據/proc/sys/net/core/somaxconn值與傳入的backlog值,選擇兩者中的小值作為已建立連接但未被伺服器accept的連接隊列長度。

netstat -na |grep PORT | grep LISTEN 可以查看到監聽句柄的recv-q隊列大小,如果該值較大升值>=backlog值,說明伺服器無法適應當前連接建立速度,不能及時的accept新連接,此時即使伺服器內部統計無壓力,各種請求處理指標都正常也會影響外部服務,因為新的連接可能會失敗(不失敗也會等待較長時間才被伺服器處理,而此時可能客戶端已經超時重連了...一旦發生這種情形就會惡性循環-連接一直建立,但每個連接都失敗)。

三、小結

通過抓包工具及網路狀態查看命令netstat可以幫助定位客戶端、服務端相關網路問題,在日誌匱乏或性能統計信息不足以分析伺服器問題時,可以輔助分析伺服器相關模塊性能。

喜歡就點個贊再走嘛!歡迎關注我們的公眾號哦!


推薦閱讀:
相關文章