TCP/IP-over-Ethernet 網路中的延遲

TCP/IP-over-Ethernet 網路中的延遲

您會推薦哪些資源(書籍、網頁等):

  • 解釋 TCP/IP-over-Ethernet 網路中延遲的原因;
  • 提及用於尋找導致延遲的事物的工具(例如 中的某些條目netstat -s);
  • 建議調整 Linux TCP 堆疊以減少 TCP 延遲的方法(Nagle、套接字緩衝區等)。

我知道的最接近的是這個文件,但它相當簡短。

或者,歡迎您直接回答上述問題。

編輯需要明確的是,問題不僅僅是關於「異常」延遲,而是關於一般延遲。此外,它專門涉及乙太網路上的 TCP/IP,而不是其他協定(即使它們具有更好的延遲特性。)

答案1

關於延遲的核心可調參數,需要注意的是:

echo 1 > /proc/sys/net/ipv4/tcp_low_latency

來自文件:

如果設置,TCP 堆疊會做出傾向於較低延遲而不是較高吞吐量的決策。預設情況下,未設定此選項,這意味著首選更高的吞吐量。 Beowulf 計算叢集就是一個應更改此預設值的應用程式範例。預設值:0

您也可以在應用程式中停用 Nagle 演算法(它將緩衝 TCP 輸出直到最大段大小),如下所示:

#include <sys/types.h>
#include <stdio.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <stdlib.h>
#include <linux/tcp.h>

int optval = 1;
int mysock;

void main() {
    void errmsg(char *msg) {perror(msg);exit(1);}

    if((mysock = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0) {
        errmsg("setsock failed");
    }

    if((setsockopt(mysock, SOL_SOCKET, TCP_NODELAY, &optval, sizeof(optval))) < 0) {
        errmsg("setsock failed");
    }

    /* Some more code here ... */

    close(mysock);
}

該選項的“相反”是TCP_CORK,它將“重新 Nagle”資料包。但請注意,TCP_NODELAY可能並不總是符合您的預期,並且在某些情況下可能會損害效能。例如,如果您要傳送批量數據,您將希望最大化每個資料包的吞吐量,因此設定TCP_CORK。如果您的應用程式需要立即互動(或回應遠大於請求,從而消除開銷),請使用TCP _NODELAY.另一方面,這種行為是 Linux 特有的,而 BSD 可能有所不同,所以警告管理員

確保對您的應用程式和基礎設施進行徹底的測試。

答案2

根據我的經驗,最大的原因是異常其他健康的高速網路上的延遲是 TCP 視窗(RFC1323,第 2 節)故障,與 TCP 延遲確認故障中的第二個密切相關(RFC1122 第 4.2.3.2 節)。這兩種方法都是 TCP 的增強,以便更好地處理高速網路。當它們損壞時,速度會降至非常慢的水平。這些情況下的故障會影響大型傳輸(例如備份流),而極事務性的小流量(平均資料傳輸低於 MTU 大小並且存在大量來回)受這些影響較小。

再次,當兩個不同的 TCP/IP 堆疊進行通訊時,我發現了這兩個問題的最大問題。例如Windows/Linux、2.4-Linux/2.6-Linux、Windows/NetWare、Linux/BSD。非常非常喜歡作品。 Microsoft 在 Server 2008 中重寫了 Windows TCP/IP 堆疊,這引入了 Server 2003 中不存在的 Linux 互通性問題(我相信這些問題已解決,但我無法 100% 確定)。

對延遲或選擇性確認的確切方法的分歧可能會導致如下情況:

192.168.128.5 -> 192.168.128.20:1500b 有效負載,SEQ 1562
192.168.128.5 -> 192.168.128.20:1500b 有效負載,SEQ 9524
[200ms通過]
192.168.128.20 -> 192.168.128.5:ACK 1562
192.168.128.5 -> 192.168.128.20:1500b 有效負載,SEQ 12025
192.168.128.5 -> 192.168.128.20:1500b 有效負載,SEQ 13824
[200ms通過]
192.168.128.20 -> 192.168.128.5:ACK 12025

由於所有 200 毫秒逾時,吞吐量下降(Windows 預設延遲確認計時器為 200 毫秒)。在這種情況下,會話雙方都無法處理 TCP 延遲確認。

TCP 視窗故障更難注意到,因為它們的影響可能不太明顯。在極端情況下,視窗化完全失敗,您會得到 packet->ack->packet->ack->packet->ack,這在傳輸任何明顯大於 10KB 的數據時非常慢,並且會放大任何數據基本潛伏期在連結上。更難檢測的模式是雙方不斷重新協商其視窗大小,而一方(發送方)未能遵守協商,這需要處理一些資料包才能繼續傳遞資料。此類故障在 Wireshark 追蹤中以紅色閃爍的指示燈顯示,但表現為低於預期的吞吐量。


正如我所提到的,上述問題往往會困擾大額轉帳。它們可以真正解決諸如串流影片或備份串流之類的流量,以及簡單下載非常大的檔案(例如 Linux 發行版 ISO 檔案)。碰巧,TCP 視窗被設計為解決基本延遲問題的一種方法,因為它允許資料流水線化;您不必等待發送的每個資料包的往返時間,您可以只發送一個大塊並等待單個 ACK​​,然後再發送更多資料包。

也就是說,某些網路模式不會從這些解決方法中受益。高度事務性的小額傳輸(例如由資料庫產生的傳輸)受到的影響最大普通的線路延遲。如果 RTT 較高,這些工作負載將受到很大影響,而大型串流工作負載受到的影響要小得多。

答案3

這個問題有很多答案。

記住 TCP 的工作原理。客戶端發送 SYN,伺服器應答 SYN/ACK,客戶端應答 ACK。伺服器收到 ACK 後,就可以發送資料了。這意味著您必須等待 2 倍的往返時間 (RTT) 才能發送第一個有意義的資料。如果 RTT 為 500 毫秒,則從一開始就會有 1 秒的延遲。如果會話持續時間短但數量眾多,則會產生大量延遲。

一旦建立會話,伺服器就發送必須由客戶端確認的資料單元。伺服器在需要確認第一個資料單元之前只能發送這麼多資料。這也會產生延遲。如果資料單元遺失,您必須從那裡恢復傳輸,從而產生額外的延遲。

在IP層面,存在碎片化(儘管​​現在這種情況相當罕見)。如果您傳送 1501 位元組的幀,而另一端僅支援 1500 的 MTU,則您將為最後一位資料傳送額外的 IP 封包。這可以透過使用巨型幀來克服。

提高 TCP/IP 吞吐量的最佳方法是盡可能減少延遲並盡可能避免傳輸錯誤。我不知道有任何內核調整,但我相信有人會的。

答案4

可能不是您正在尋找的答案:WAN 中延遲的主要原因是光速(太慢了!)。此外,沿途具有大緩衝區的飽和鏈路往往會獲得令人印象深刻的延遲。

相關內容