Reverse-Proxy

如何調整 TCP 以實現兩個節點之間的高頻連接

  • December 1, 2019

在過去的幾天裡,我一直在摸不著頭腦,試圖為以下問題提出解決方案:

在我們的數據中心,我們有一個在 BigIP 硬體上執行的 F5,它充當來自全國各地辦公地點的客戶端電腦的 HTTPS 請求的單一入口點。F5 終止 TLS,然後將所有請求轉發到兩個 Traefik 負載均衡器,後者將請求分發到各種服務實例(Traefik 節點在 Red Hat Enterprise 上的 Docker 中執行,但我認為這與我的問題無關)。從吞吐量、CPU 和記憶體的角度來看,這三個網路組件完全有能力處理大量的請求和流量,並且有足夠的空閒容量。

但是,我們注意到客戶端發出的 HTTP(S) 請求經常出現 1000 毫秒的延遲,尤其是在高負載時間。我們將問題追踪到以下根本原因:

  • 在高負載期間,F5“客戶端”以高頻率(可能每秒 100+)向 Traefik“伺服器”節點發起新的 TCP 連接。
  • 當 HTTP 響應返回時,這些連接將在 Traefik “伺服器”端終止。
  • 每個關閉的連接在 Traefik 主機上保持 TIME_WAIT 狀態 60 秒。
  • 當 F5 發起新連接時,它會從其臨時埠範圍中隨機選擇一個可用埠。
  • 有時(通常在高負載期間),Traefik 中已經有一個處於 TIME_WAIT 狀態的連接,具有相同的源 IP + 埠、目標 IP + 埠組合。發生這種情況時,Traefik 主機上的 TCP 堆棧 (?) 會忽略第一個 SYN 數據包。注意:RFC 6056稱這種衝突為 instance-ids
  • 1000 毫秒後,重傳超時 (RTO) 機制在 F5 上啟動並重新發送 SYN 數據包。這次 Traefik 主機接受連接並正確完成請求。

顯然,那些 1000ms 的延遲是絕對不能接受的。所以到目前為止,我們已經考慮了以下解決方案:

  1. 減少 F5 中的 RTO 以更快地重新傳輸,例如減少到 200 毫秒。
  2. 減少 net.ipv4.tcp_fin_timeout 以更快地關閉放棄的 TIME_WAIT連接。

***更新:*這僅適用於對方放棄的連接,當沒有返回 FIN 時。它對 TIME_WAIT 狀態的連接沒有任何影響。 3. 啟用 net.ipv4.tcp_tw_reuse:對傳入連接無用。 4. 啟用 net.ipv4.tcp_tw_recycle:如果客戶端發送隨機 TCP 時間戳,則表明 AFAIK 是相反的。矛盾的資訊(包括經驗證據)是否從 Linux 中刪除了此功能。另外,一般建議不要亂用。 5. 添加更多源 IP 和/或讓 Traefik 在多個埠上偵聽以增加 IP/埠元組中的排列數。

我會丟棄#1,因為那隻是一個創可貼。延遲仍然存在,只是不太明顯。#3 無論如何都不會產生任何影響,#4 很可能會使系統無法正常工作。剩下~~#2~~和#5。

但是根據我在閱讀了幾十篇文章和技術文章後了解到的情況,它們最終只會減少那些“碰撞”的機會。因為,最終阻止發送方 F5(偽)隨機選擇在目標 Traefik 主機上仍處於 TIME_WAIT 狀態的臨時埠、源 IP 和目標埠的組合,無論 fin_timeout 設置有多短(即無論如何應該保持在許多秒範圍內)?我們只會減少碰撞的可能性,而不是消除它。

經過我所有的研究以及在巨大的 Web 應用程序時代,我真的很驚訝這個問題在 Web 上沒有得到更多討論(以及可用的解決方案)。我非常感謝您對 TCP 領域是否有更好、更系統的解決方案的想法和想法,該解決方案將推動發生接近零的衝突。我正在考慮 TCP 配置的構想,該配置將允許 Traefik 主機立即接受新連接,儘管舊連接處於 TIME_WAIT 狀態。但截至目前,沒有運氣找到那個。

隨意的想法和要點:

  • 在這一點上,改變我們的各種內部應用程序以使用執行時間更長的 HTTP(S) 連接來減少每秒的請求/連接數是不可行的。
  • F5 和 Traefik 的網路架構不討論,不能改變。
  • 我最近調查了 Windows 客戶端上的臨時埠選擇。該算法似乎是順序的,而不是隨機的。最大限度地延長埠被重用的時間,降低安全性。
  • 在其他空閒系統上進行負載測試期間,我們每秒生成約 100 個 HTTP 請求/連接。即使 F5 配置為使用超過 60k 的臨時埠,第一次沖突已經在幾秒鐘後發生(比如在總共 2000 個請求之前)。我認為這是由於埠選擇算法的偽隨機性,它似乎在避免實例 ID 衝突方面做得相當糟糕。
  • Traefik 主機在 SYN 數據包重傳時接受 TCP 連接這一事實可能是 TCP 實現的一個特性。RFC6056 談到了TIME_WAIT 暗殺,這可能與此有關。

更新:根據Star Experiment,net.ipv4.tcp_fin_timeout 設置不會影響 TIME_WAIT 狀態,只會影響 FIN_WAIT_2 狀態。根據Samir Jafferali的說法,在 Linux 系統(包括我們的 Red Hat Linux)上,TIME_WAIT 時間段是硬編碼在原始碼中的,無法配置。根據來源,在 BSD 上它是可配置的,但我還沒有驗證這一點。

在我們的數據中心,我們有一個在 BigIP 硬體上執行的 F5,它充當來自**我們在全國各地辦公地點的客戶端電腦的HTTPS 請求的單一入口點

如果這個單點(前端)在將連接向下傳遞到後端時仍然是單點,您為什麼想知道這些問題?特別是如果連接強度是“每秒可能 100+”。

您的設置基本上是將一組具有較高基數的集合壓縮到另一個具有顯著較低基數的集合中。

最終只會減少那些“碰撞”的機會

這是分組交換網路如何工作的基礎。比如說,在乙太網級別也有衝突。隨機性是不可避免的,TCP/IP 正在處理它。實際上,IP 協議本身的建構並沒有考慮到 LAN(但在那裡仍然很好用)。

所以是的,“添加更多源 IP 和/或讓 Traefik 在多個埠上偵聽”是非常合理的遵循方式。

引用自:https://serverfault.com/questions/992675