全球網路 Google Cloud 可連線至不同區域和可用區的應用程式,不必離開 Google 網路,即可提供高可靠性和低延遲。不過,預設的 Linux TCP/IP 設定通常是針對地端環境調整,可能會導致雲端效能瓶頸。
如要讓 Google Cloud發揮最佳效能,請使用本文中專為雲端環境最佳化的 TCP/IP 設定。
本文提及的設定已在Google Cloud 環境中測試過。這些設定主要用於內部執行個體通訊,不一定適用於 Compute Engine 執行個體與外部位址之間的通訊。
瞭解處理量上限
TCP 會使用「時間區間設定」機制管理傳送方和接收方之間的資料流。可達到的最大總處理量取決於下列關係:
Throughput <= window size / round-trip time (RTT) latency
在原始的 TCP 設計中,時間區間大小上限為 65535 個位元組 (64 KiB 減 1),這通常會導致現代高速網路無法充分發揮效用,因為傳送端會等待時間區間更新。
最佳化 TCP 效能的 Shell 指令碼
建議採用下列 TCP 設定,提升效能:
- 縮短 MinRTO:縮短重新傳輸延遲時間,更快從封包遺失中復原。
- 啟用公平佇列:盡量減少因應用程式爆量而造成的壅塞和捨棄情形。
- 在閒置後停用緩慢啟動:在連線閒置一段時間後,以最後已知的良好傳輸速率重新啟動。
- 停用 TCP Cubic HyStart ACK 訓練:在提高資料傳輸速率時,忽略誤報的壅塞信號。
- 提高通訊端記憶體預算:提高每個連線允許的最大傳輸中資料量。
- 啟用硬體 GRO:將資料合併為較少但較大的封包,提高大型資料流的 TCP/IP 接收處理效率。
- 將 MTU 增加至 4082 位元組:提高高輸送量流量的傳輸效率。
您可以使用下列 Shell 指令碼啟用這些建議設定。執行指令碼前,請務必將 eth0 替換為運算執行個體的主要網路介面。
# Set DEV to your primary network interface
DEV=eth0
# 1. Reduce MinRTO
sysctl -w net.ipv4.tcp_rto_min_us=5000
# 2. Enable Fair Queueing
tc qdisc replace dev $DEV root fq
# 3. Disable slow start after idle
sysctl -w net.ipv4.tcp_slow_start_after_idle=0
# 4. Disable TCP Cubic HyStart ACK train
echo 2 > /sys/module/tcp_cubic/parameters/hystart_detect
# 5. Increase socket memory budgets
echo 4194304 > /proc/sys/net/core/rmem_max
echo 4194304 > /proc/sys/net/core/wmem_max
echo 4194304 > /proc/sys/net/ipv4/tcp_notsent_lowat
echo "4096 262144 16777216" > /proc/sys/net/ipv4/tcp_rmem
echo "4096 262144 33554432" > /proc/sys/net/ipv4/tcp_wmem
# 6. Enable hardware GRO
ethtool -K $DEV rx-gro-hw on
以下各節將詳細說明每項建議的設定。
減少 MinRTO
減少重新傳輸延遲,更快從封包遺失中復原。
TCP 重新傳輸逾時 (RTO) 會控管 TCP 傳送端等待 ACK 信號的時間長度,之後才會重新傳輸。Linux 會將 RTO 初始化為一秒 (根據 RFC 6298 第 2.1 節),然後隨著時間調整為往返時間 (RTT) 加上安全邊際。
最低 RTO (MinRTO) 會對這項調整設下限。如果 RTO 估算值過低,可能會導致偽造的重新傳輸,也就是傳送端在處理回應時重新傳輸封包。
預設的 MinRTO 為 200 毫秒,對於現代雲端網路而言,這個值過於保守。我們在Google Cloud 中進行了廣泛測試,發現 5 毫秒的值是 Google Cloud內現代 Linux 伺服器之間連線的安全預設值。
另一個因素是延遲 ACK,也就是對等互連延遲 ACK 回應。這項延遲可讓系統將多個資料封包的 ACK 分批傳送,或將 ACK 與反向的資料封包合併傳送。延遲 ACK 計時器是以 RTT 為基礎,與 RTO 計時器類似。
降低 MinRTO 可加快低 RTT 連線 (例如區域或地區內的連線) 的封包遺失修復速度。這項調整不會影響 RTT 較高的連線行為,因為這項調整不會變更預估 RTT。
設定 MinRTO
您可以透過下列任一方式設定 MinRTO:
使用
sysctl(Linux 6.11 以上版本):您可以使用
sysctl指令設定預設 MinRTO:sysctl -w net.ipv4.tcp_rto_min_us=5000使用
ip route(每個路徑的控制項,或 Linux 6.11 之前的版本):或者,如果是舊版 Linux 或需要依據路徑進行控制,可以依據路徑設定 MinRTO:
ip route change default rto_min 5ms
如果連線可能會離開 Google Cloud 或與非 Linux TCP/IP 堆疊通訊,建議採用依路徑方法。這些系統的延遲 ACK 計時器可能不同。如要廣泛部署公用網際網路,建議保留保守的預設 minRTO 設定,並僅將 5 毫秒設定套用至 Google Cloud 虛擬私有雲內的路由。
啟用公平佇列
盡量減少應用程式爆量造成的壅塞和封包遺失。
與標準先進先出 (FIFO) 佇列不同,公平佇列 (FQ) 會在不同流量之間公平分配頻寬。此外,這項功能還會為每個封包計算最佳傳送速率和時間,藉此控管流量。如果存在 FQ,TCP 堆疊會依賴 FQ 保留封包,直到最佳傳輸時間為止。這種步調可減少流程中的突發狀況,進而減少封包遺失和重新傳輸的情況。
如要將 FQ 流量整形器設為網路裝置流量整形器,請使用下列 tc (流量控制) 指令:
tc qdisc replace dev $DEV root fq
在高輸出頻寬的大型執行個體上,網路裝置可能有多個傳輸佇列。對於這些執行個體,建議您安裝多重佇列 (MQ) 流量整形器,在傳輸佇列之間分片流量整形。這是多工器,會將獨立的流量整形器附加至每個傳輸佇列。每個佇列的流量整形器可減少 CPU 間的鎖定和快取行爭用。
停用閒置後的緩慢啟動功能
連線閒置後仍維持高傳輸速率。
為避免壅塞,TCP 連線會先以低速率傳送資料,然後以指數方式提高速率,直到偵測到封包遺失為止。這個初始階段稱為「緩慢啟動」。
根據預設,TCP 會在閒置一段時間後,還原為保守的「慢速啟動」設定。閒置期最短可為一個重新傳輸逾時 (RTO),如 RFC 2581 所定義。停用這項功能後,連線就能立即以最後已知的良好速率繼續運作。
如果可以,應用程式應使用長期連線,而非重複與相同對等互連建立連線。這樣可避免建立連線的成本,並維護壅塞資訊。不過,即使連線時間較長,TCP 預設也會在閒置一段時間後忘記壅塞資訊,並還原為初始保守設定和「緩慢啟動」階段。
如要停用閒置後緩慢啟動功能,請使用下列指令:
sysctl -w net.ipv4.tcp_slow_start_after_idle=0
停用 TCP Cubic HyStart ACK 訓練
忽略偽陽性壅塞訊號,快速擴展至高傳輸速率。
「緩慢啟動」階段的指數成長率可能較高,因此可能會超過最佳目標比率。混合式啟動 (HyStart) 是一種額外機制,可使用兩項重要的壅塞信號,提早結束「緩慢啟動」階段:
- 封包往返時間 (RTT) 延遲:測量封包在網路中的傳播延遲。網路擁塞期間,封包佇列會在瓶頸連結中累積。這會導致 RTT 增加,可能表示出現壅塞情形。
- ACK 間距:依據封包在瓶頸處延遲的信號,但著重於回應 ACK。這項機制假設在沒有壅塞的情況下,ACK 的抵達間隔與原始資料封包相同。這種模式通常稱為 ACK 列車。如果 ACK 延遲的時間超出預期模式,表示可能發生壅塞。
如要盡量提升效能,請停用 ACK 封包列車偵測功能,同時保持 RTT 延遲機制啟用狀態。
echo 2 > /sys/module/tcp_cubic/parameters/hystart_detect
提高插槽記憶體預算
允許更多傳輸中資料,提高高 RTT 連結的最高處理量。
傳輸中的資料量是頻寬和傳播延遲的函式,稱為頻寬延遲乘積 (BDP)。計算方式是頻寬乘以封包往返時間 (RTT),所得的值就是為了要填滿管線而須傳送的最佳位元數:
BDP (bits) = bandwidth (bits/second) * RTT (seconds)
所有機上資料都必須保留在傳送端的緩衝區,以防需要重新傳輸。TCP Socket 記憶體限制會決定可緩衝處理的傳輸中資料量,因此可直接限制可達到的輸送量。
在 Linux 中,TCP 通訊端記憶體限制是透過下列sysctl(8)設定進行設定:
net.core.rmem_maxnet.core.wmem_maxnet.ipv4.tcp_rmemnet.ipv4.tcp_wmem
設定這些 TCP 通訊端記憶體上限,是為了避免用盡所有系統記憶體,導致記憶體不足 (OOM) 情況,尤其是在連線數眾多的工作負載中。提高這些限制可以增加總處理量,尤其是在高 RTT 路徑上。除非連線數達到數百萬,否則提高這些限制的風險很小。
這些變數會設定通訊端緩衝區大小的上限,而非直接分配記憶體。如果連線的 RTT 較低 (例如在 Google Cloud 區域內),增加這些值不會影響連線的實際記憶體分配。
前兩個可微調參數會影響直接設定 TCP 時間區間大小的應用程式,但這類應用程式相對較少。這些限制會決定應用程式可透過通訊端選項 SO_RCVBUF 和 SO_SNDBUF 明確要求的值。
如果是 Linux 核心 6.18 以上版本,net.core.rmem_max 和 net.core.wmem_max 預設為 4 MB。根據多年經驗,這些設定被視為安全。如果是較舊的 Linux 版本,建議您在現代平台上將這些限制提高至 4 MB:
echo 4194304 > /proc/sys/net/core/rmem_max
echo 4194304 > /proc/sys/net/core/wmem_max
第二組限制 net.ipv4.tcp_rmem 和 net.ipv4.tcp_wmem 則是用來管理 TCP 傳送和接收緩衝區的自動微調限制。
這些設定各需要三個值:最小、初始預設和最大通訊端記憶體大小。預設最大值通常比現代平台上的需求更保守,例如:
tcp_rmem:4096、131072、6291456tcp_wmem:4096、16384、4194304
TCP 堆疊會根據 RTT 和壅塞視窗的估計值,自動調整 TCP 傳送和接收緩衝區的大小。寫入緩衝區大小上限為 4194304 (即 4 MB),對於高 RTT 連線來說太小;如果 RTT 為 100 毫秒,這個設定在最佳情況下會將處理量限制為 40 MB/秒。與其嘗試計算要使用的值,不如採用較簡單的方法,為具有多個 GB RAM 的現代伺服器使用安全預設值。
為確保安全,建議您限制可在通訊端中排隊但尚未傳送的資料量。雖然增加最大wmem的目的是允許更多資料在傳輸中,但程序寫入通訊端的速度可能比 TCP 傳送資料的速度快,導致主機上累積未傳送的資料佇列,浪費記憶體。為避免發生這種情況,請設定 tcp_notsent_lowat,限制尚未傳送的資料量,然後提高整體 wmem 限制,允許較大的傳輸中緩衝區
除非伺服器有數百萬個連線,否則下列設定應該很安全。不過,如果連線數量過多導致記憶體不足,請使用較小的緩衝區大小上限。
echo 4194304 > /proc/sys/net/ipv4/tcp_notsent_lowat
echo "4096 262144 16777216" > /proc/sys/net/ipv4/tcp_rmem
echo "4096 262144 33554432" > /proc/sys/net/ipv4/tcp_wmem
啟用硬體 GRO
提高大型流量的 TCP/IP 接收處理效率。透過批次處理收到的封包,減少 CPU 負擔
對於大多數 TCP/IP 作業,CPU 週期成本會隨著封包速率而變化,而非位元組速率。為減輕傳輸負擔,現代作業系統會透過傳輸路徑,以包含多個 TCP 區隔的大型封包傳送 TCP 資料。這些範圍可達 64 KB,甚至使用 Linux BIG-TCP 時可達數百 KB。
這類大型封包會超過網路上的封包大小上限 (即 MTU)。這項作業系統最佳化功能需要網路裝置支援,才能將這些封包分割成一連串較小的封包,每個封包都只包含一個 TCP 區段。這項支援功能 (TCP 區隔卸載,簡稱 TSO) 廣為可用,且預設為啟用。
接收時,第三代和更新平台上的 GVNIC 裝置可以執行反向作業:在裝置中暫時緩衝處理區段,查看是否連續抵達區段,如果是,則合併區段並以多區段封包的形式轉送至主機。這項功能在 Windows 中稱為「接收區段合併 (RSC)」,在 Linux 中則稱為「大型接收卸載 (LRO)」或「硬體通用接收卸載 (HW-GRO)」。HW-GRO 是 LRO 的嚴格版本。
HW-GRO 預設為啟用,這項功能最終會在適用地區推出。
在此期間,在支援這項功能的 GVNIC 裝置平台上,請使用 ethtool 啟用 HW-GRO。視核心和驅動程式版本而定,這項功能會宣傳為 LRO 或 HW-GRO。無論名稱為何,實作方式都相同。
ethtool -K $DEV large-receive-offload on
ethtool -K $DEV rx-gro-hw on
將 MTU 大小增加至 4082 位元組
提高高總處理量資料流的資料移轉效率。
增加封包大小 (類似於 TSO 和 HW-GRO 最佳化),可提升傳輸效率,因為大部分的處理作業都是以封包為單位,而非以位元組為單位。
Google Cloud 虛擬私有雲網路可支援大小上限為 8898 個位元組的封包,遠大於預設的 1460 個位元組。使用較大的網路封包大小,可減少每個位元組處理量 (有效處理量) 所耗用的 CPU 週期。
封包大小最佳化注意事項
雖然封包越大通常越好,但最大 MTU 不一定是最佳選擇。減少傳送封包所帶來的效益,必須與下列成本相抵:
- 記憶體用量:緩衝區越大,網路裝置接收封包時所需的記憶體就越多。如果佇列數量眾多,可能會導致大量記憶體閒置。
- 小型封包處理:較大的緩衝區處理小型封包 (例如純確認 (ACK)) 的效率較低。
- CPU 分配成本:資料路徑成本會受到記憶體分配和釋放的影響。將封包大小調整為記憶體頁面的倍數,有助於盡量降低 CPU 成本。
- TSO 互動:封包大小會稍微影響 TCP 區隔卸載 (TSO)。如要建構盡可能大的 TSO 封包,您可能需要選擇較小的最大區段大小 (MSS)。舉例來說,假設最大可能的 IP 封包為 64 KB (包括標頭),則 MSS 為 4 KB 時,酬載會大於 MSS 為 8 KB 時 (分別為 60 KB 和 56 KB)。
對於大多數工作負載,4 KB、8 KB 或 9 KB MTU 之間的效率差異很小。不過,相較於預設的 1460 位元組封包,上述任一值都是大幅改善。
建議的頁面大小封包
我們建議將 VPC 網路的 MTU 大小設為 4082 位元組,因為這個選項穩定且通常效率很高。建議使用這個大小,是因為這樣一來,整個乙太網路封包就能容納在 4096 位元組的記憶體頁面中,進而最佳化記憶體頁面配置。這項建議適用於第 3 層 MTU,包括 IP 標頭,但不包括 14 位元組的乙太網路連結層。
IP MTU 設定
您可以直接透過 Google Cloud 控制台,為每個 VPC 網路設定 MTU。
在大多數 Linux 發行版中,不需要在運算執行個體上進行手動設定。 Google Cloud執行個體會在啟動期間使用 DHCP (透過選項 26) 自動瞭解網路 MTU。執行個體隨後會設定網路裝置 MTU,使其相符。建議使用這項自動設定。
如有必要手動設定,可以使用下列指令,將網路裝置 MTU 設為低於虛擬私有雲網路 MTU 的值:
ip link set dev $DEV mtu 4082
為特定路徑設定不同的 MTU 大小
如果運算執行個體在虛擬私有雲外部進行外部通訊,路徑 MTU 可能較低,因此建議在特定路徑上設定 MTU。在這種情況下,請將預設 MTU 設為保守的 1460 位元組,並僅將較高的 MTU (例如 4082 位元組) 套用至 VPC 內部的路由:
#Set intra-VPC route MTU:
ip -4 route change $SUBNET/$MASK dev $DEV mtu 4082
#Set default route MTU:
ip -4 route change default dev $DEV mtu 1460
設定 TCP 最大區段大小 (MSS)
TCP 最大區隔大小 (MSS) 會決定 TCP 連線的封包酬載大小。由於 TCP/IP 封包不得超過 MTU 大小,以免封包遭到分段或捨棄,因此 MSS 必須相應調整。
一般來說,您不需要手動設定 TCP MSS,因為作業系統會自動從路徑 MTU 衍生出 TCP MSS。
MSS 涵蓋酬載和 TCP 選項,但不含 20 位元組的 IPv4 標頭和 20 位元組的 TCP 標頭。因此,在 IPv4 網路上,MSS 通常比 MTU 小 40 個位元組。
如要為特定流量設定較小的 MSS,可以針對個別路徑進行設定。舉例來說,如果您的 VPC 網路和裝置 MTU 使用一般流量的最大值 (8896 個位元組),但您想為 TCP 流量使用 4 KB MTU,可以執行下列指令:
ip -4 route change default dev $DEV advmss 4042
標頭分割模式
第三代平台提供選用的接收標頭分割功能,預設為停用。
標頭分割會將封包標頭和資料分割到不同的緩衝區。這可讓您在整個記憶體頁面填入 4096 位元組的資料。這種分離方式可進行重要最佳化,例如以較便宜的記憶體頁面對應作業 (例如使用 Linux TCP_ZEROCOPY_RECEIVE),取代耗費資源的核心到使用者空間複製作業。
啟用接收標頭分割功能後,MTU 計算方式會有所不同。 最佳 MTU 是指所有標頭都對應至標頭緩衝區,且酬載緩衝區填滿一整頁資料。啟用標頭分割功能:
- 標頭緩衝區包含:
- 乙太網路 (14 個位元組)
- IPv4 (20 個位元組)
- TCP (20 位元組) 標頭
- 常見的 TCP 選項 (預設設定為使用 TCP 時間戳記時為 12 個位元組)
- 資料緩衝區會保留 4096 位元組的酬載資料。
因此總訊框大小為 4162 位元組,MTU 為 4148 位元組。
後續步驟
- 閱讀提高網路效能的 5 個步驟 Google Cloud 網誌文章。
- 瞭解全球網路產品。
- 瞭解網路層級 Google Cloud。
- 瞭解如何評估網路效能。