ping命令持續發送少量互聯網流量到遠程地址并報告收到回應的總時間。如果流量因為網絡故障或者錯誤配置而被丟棄,它也會報告。ping命令是最基本和初級的診斷網絡問題的工具之一。
ping常被用來測試網絡延遲,但是有時ping的延遲并不是網絡引起的,所以為了正確理解ping的結果,有必要了解影響ping延遲的幾個因素。
ping的原理是通過發送ICMP echo request包,在收到ICMP echo reply包之后,計算發送時間與接收時間之間的差值,得出延遲的時間。ping的輸出舉例如下:
ping缺省每秒發一個echo request,發包的時候不會輸出任何信息,直至收到echo reply的時候才輸出一條信息,格式如上,最后一列是延遲時間,ms表示毫秒。
影響ping延遲的因素主要有:
ping延遲包含了進程調度的延遲
由于ping本身是用戶態的程序,它首先會受到進程調度的影響,比方說高優先級的進程與ping爭搶CPU的話,ping的執行就會遭到拖延,這個調度延遲如果是發生在發包之后、收包之前,就會被計入ping的延遲之中。
多個同時運行的ping進程之間會互相干擾,導致延遲
ping通過raw socket發送和接收ICMP包,而raw socket不僅會收到給自己的包,也會收到給別人的包,假如有多個ping進程同時在運行,你的ping就有可能會收到別人的ping的echo reply,當然,ping程序可以從中挑出給自己的包,因為包里嵌入了對應的ping進程號,但是每個包都打開看看、并判斷是不是給自己的——這都要消耗時間的,所以說,多個ping進程之間會互相干擾,導致延遲加大。不同的UNIX版本由于實現方式的差異,受這個因素的影響程度也不一樣,比如HP-UX受影響較大,而Linux受影響相對較小,因為Linux采用了一種過濾機制:Linux Socket Filtering,亦即Berkeley Packet Filter (BPF),ping程序利用BPF給raw socket加上一個過濾器,這樣內核會只把對應的echo reply傳遞給ping程序,給其他ping進程的echo reply不會再傳給這個ping,避免了CPU和buffer資源的浪費,也減少了ping延遲。
其他類型的ICMP包也會對ping造成干擾
ICMP包有好幾種類型,ping希望收到的是ICMP_ECHOREPLY,但是其他類型的包也都會傳遞給ping,我們上面說過,這是因為ping使用raw socket的緣故,raw socket會看到所有的ICMP包。ping需要消耗額外的時間和資源去查看這些本來不相干的包,故而有可能會產生延遲。以下列出各種ICMP包的類型供參考:
ICMP_ECHO
ICMP_ECHOREPLY
ICMP_SOURCE_QUENCH
ICMP_REDIRECT
ICMP_DEST_UNREACH
ICMP_TIME_EXCEEDED
ICMP_PARAMETERPROB
注1:在Linux上,雖然ping采用了BPF過濾機制,但是只過濾掉了發給其他ping進程的ICMP_ECHOREPLY包,其他類型的包是不過濾的,所以仍然會受到影響。
注2:在HP-UX上ICMP_SOURCE_QUENCH是最常見的影響ping延遲的因素。Source Quench是一種簡陋的流控機制,當接收端有緩沖區滿的時候,通過向發送端返回Source Quench,告知發送端降低發送速度,而滿溢的緩沖區不一定與ICMP有關,更常見的事UDP的緩沖區。由于這種機制存在種種問題,有許多反對使用Source Quench的聲音,比如:RFC6633。Linux從2.2起就不再支持ICMP Source Quench了。
還有些其它因素,比如網卡驅動,防火墻軟件什么的,但比較少見,就不深入探討了。
怎樣判斷ping延遲是網絡延遲還是其它因素導致的呢?
如果有1秒以上的延遲的話,觀察一下icmp_seq,它表示包的順序,在下例中,第3個包的延遲是2.068秒,而第4個包的延遲只有0.183秒,如果發包的頻率嚴格保持每秒一次的話,第4個包應該比第3個包先收到才對,而下例中,包的順序并未顛倒,這說明第4個包的發送也被延遲了。發送延遲,那就不是網絡延遲了,肯定有其它原因。
還有一個簡單的方法可以一試,ping一下127.0.0.1或者ping本機的IP地址,它們不用通過網絡,甚至不用進入網卡驅動程序,所以延遲應該非常小,可以作為一個基準值,如果它們的延遲比較大,那最大的可能是存在調度延遲或者ICMP包干擾之類的問題。