網絡丟包故障分析

某臺「Nginx / PHP」服務器時不時出現HTTP服務卡住的現象。

開始我懷疑PHP有問題,但是通過查詢Nginx的access日誌,發現裏面記錄的PHP響應時間「$upstream_response_time」非常小,此外還通過Strace命令仔細覈對了是否存在耗時的操作,結果一無所獲,所以基本排除了PHP的嫌疑。

接着我把目光轉移到了Nginx身上,琢磨着是不是Nagle算法導致的網絡延遲,不過Nginx缺省就通過「tcp_nodelay」指令關閉了Nagle算法,所以基本排除了Nginx的嫌疑。

既然Nginx和PHP都有不在場的證據,那會不會是Linux內核參數的問題呢?因爲這臺Web服務器前面有NAT方式的LVS,所以如果「tcp_timestamps」和「tcp_tw_recycle」等內核參數設置不當的話,會導致網絡故障,可是通過檢查再次否定了這個推斷。

問題到了這裏似乎陷入了僵局,看來瞎蒙是沒戲了,只好硬着頭皮用tcpdump了,說硬着頭皮是因爲我這個山寨OPS對TCP協議實在是不熟悉,但是爲了解決問題,只能趕鴨子上架了,找一個客戶端重現故障,然後在服務端監聽:

shell> tcpdump -i eth0 host <CLIENTIP> and port 80

不出意外是一大堆天書般的結果,一句話:法海你不懂愛。好在菜鳥有菜鳥的玩法,祭出神器:Wireshark,可以通過它來可視化分析tcpdump生成的日誌文件:

shell> tcpdump -w /path/to/log -i eth0 host <CLIENTIP> and port 80

本例中最終的效果圖大致如下所示:

通過wireshark分析tcpdump結果

通過wireshark分析tcpdump結果


黑色一看就有問題,果斷搜索:TCP Dup ACK,TCP Out-Of-Order,結果發現此類問題基本都意味着網絡狀況不好,推測網絡可能存在丟包。

如何判斷網絡是否存在丟包呢?非常簡單,通過常用的「ping」命令即可:

shell> ping -f <IP>

關於其中的「-f」選項,在手冊中是這樣解釋的:


Flood ping. For every ECHO_REQUEST sent a period “.” is printed, while for ever ECHO_REPLY received a backspace is printed.  This provides a rapid display of how many packets are being dropped. If interval is not given, it sets interval to zero and outputs packets as fast as they come back or one hundred times per second, whichever is more. Only the super-user may use this option with zero interval.


簡單點說:發送洪水請求,每個請求打印一個點,每個響應刪除一個點。如果網絡存在丟包,那麼會呈現出一長串不斷增加的點,簡單易用,童叟無欺。

最終確認了網絡確實存在丟包。總算抓住了真兇,對一個山寨的OPS來說,問題分析到這裏就算差不多了,至於爲什麼會丟包的問題,可能是網線的問題,也可能是網卡的問題,還可能是帶寬的問題,等等等等,這些就留給真正的OPS去折騰吧。


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