VPS Linux 網路調校 TCP 系統效能 sysctl

那些 sysctl 參數你貼上去了,但你知道它們在做什麼嗎?

網路上流傳的 Linux sysctl 調校範本大多只說「貼上去效能會變好」,卻不解釋原理。這篇從 TCP 緩衝區、BBR、連線佇列到 TIME_WAIT,一一說清楚每個參數解決的是什麼問題,以及什麼情況下不該動它。

網路上有幾份 sysctl 調校範本被轉貼了幾百次,每份都說「貼上去效能會提升」。沒有人解釋為什麼,也沒有人說某幾個參數在你的環境下根本不需要動,甚至會壞事。

這篇文章想做的事情很簡單:把常見的 Linux TCP 調校參數拆開來,一個一個說清楚它在解決什麼問題、預設值在什麼情境下夠用、什麼情境下才需要調整。

先弄清楚瓶頸在哪裡

貼 sysctl 之前,先確認你的問題是不是真的出在核心 TCP 設定。幾個快速確認的方向:

1
2
3
4
5
6
7
8
9
# 看目前的 TCP 連線狀態分佈
ss -s

# 看有沒有封包被 drop
netstat -s | grep -i drop
netstat -s | grep -i overflow

# 看網路介面的錯誤與 drop
ip -s link show eth0

如果 ss -s 顯示大量 CLOSE_WAIT,問題通常在應用層的連線管理,不在核心。如果 netstat -s 顯示 SYN 被 drop,才是連線佇列的問題。瓶頸沒確認清楚就開始調 sysctl,調完也不知道有沒有用。

TCP 緩衝區:你的資料在核心裡等多久

TCP 緩衝區決定了每條連線可以暫存多少還沒被確認或還沒被應用程式讀走的資料量。這直接影響在高延遲線路上能跑出多少吞吐量。

原理是這樣的:在 RTT(往返延遲)100ms 的線路上,如果緩衝區太小,傳送端每次發完一批資料之後就得等 ACK 回來才能繼續送。這個等待時間把頻寬浪費掉了。計算式是 BDP(頻寬延遲乘積):

1
2
BDP = 頻寬(bytes/s) × RTT(s)
例:1Gbps × 0.1s = 12.5MB

要在 1Gbps、RTT 100ms 的線路上跑滿頻寬,緩衝區至少要 12.5MB。

相關的 sysctl 參數:

1
2
3
4
net.core.rmem_max = 134217728       # 接收緩衝區上限 (128MB)
net.core.wmem_max = 134217728 # 傳送緩衝區上限 (128MB)
net.ipv4.tcp_rmem = 4096 87380 134217728 # min / default / max
net.ipv4.tcp_wmem = 4096 65536 134217728 # min / default / max

tcp_rmemtcp_wmem 是每條連線的動態範圍,核心會根據系統記憶體壓力在這個範圍內自動調整,不需要手動為每條連線設定固定值。net.core.rmem_max 是硬上限,如果設的比 tcp_rmem 第三個值小,應用程式即使用 SO_RCVBUF 手動要求更大緩衝區也會被截斷。

什麼情況下不需要動:如果你的服務只處理臺灣境內請求,RTT 通常在 5-20ms 之間,預設緩衝區大小幾乎不會是瓶頸。緩衝區調大會佔用更多記憶體,記憶體有限的 VPS 要特別注意。

BBR:換掉的是整個壅塞控制邏輯

Linux 預設的壅塞控制演算法是 CUBIC。CUBIC 的設計假設是:發生封包遺失 = 網路壅塞,遇到遺失就退縮。這個假設在高品質、低遺失率的網路裡沒問題,但在跨洋線路或有一定遺失率的連線上,CUBIC 會把頻寬使用率壓得很低。

BBR(Google 在 2016 年提出)的思路完全不同:它持續測量線路的真實頻寬和最小 RTT,用這兩個數字估算「目前最佳傳送速率」,而不是靠遺失事件來猜測。在有封包遺失但不是真正壅塞的情境下(例如 Wi-Fi 訊號不穩、部分 ISP 的 buffer bloat),BBR 的表現比 CUBIC 好很多。

啟用方式:

1
2
3
4
5
6
7
8
9
10
11
# 確認核心是否支援
sysctl net.ipv4.tcp_available_congestion_control
# 如果有列出 bbr 就可以直接啟用

# 寫入設定
echo "net.core.default_qdisc = fq" >> /etc/sysctl.d/99-tcp.conf
echo "net.ipv4.tcp_congestion_control = bbr" >> /etc/sysctl.d/99-tcp.conf
sysctl -p /etc/sysctl.d/99-tcp.conf

# 確認生效
sysctl net.ipv4.tcp_congestion_control

net.core.default_qdisc = fq 這行也要一起設,BBR 需要 FQ(公平佇列)排程器配合,才能讓傳送速率的 pacing 發揮作用。只設 BBR 不設 FQ,效果會打折扣。

BBR 的限制:它改變的是你的主機跟對端之間的傳輸行為,但不會改變實體路由。臺北到洛杉磯的 RTT 不會因為裝了 BBR 而縮短,BBR 讓你能更充分利用現有頻寬,而不是降低延遲。

核心 6.x 已內建 BBRv3,如果你跑的是 Ubuntu 24.04 或更新的發行版,直接用就行,不需要自己編核心。

連線佇列:SYN 被 drop 的根本原因

當大量連線同時湧入,如果來不及建立完整的 TCP 三向交握,新進的 SYN 封包就會被 drop 掉。這不是防火牆,是核心的佇列滿了。

TCP 建立連線有兩個佇列:

  • SYN 佇列(半開連線,等待 ACK 回來):net.ipv4.tcp_max_syn_backlog
  • Accept 佇列(完成三向交握,等應用程式 accept()):net.core.somaxconn

somaxconn 是系統層級的硬上限,但應用程式在呼叫 listen() 時也可以指定自己的 backlog 值——兩者取較小的那個。所以光調 somaxconn 不夠,還要確認應用程式的 listen backlog 設定。Nginx 的 listen 80 backlog=65535;、Node.js 的 server.listen(port, backlog) 都要對應調整。

1
2
3
net.core.somaxconn = 65535
net.ipv4.tcp_max_syn_backlog = 65535
net.core.netdev_max_backlog = 250000

netdev_max_backlog 是網卡驅動層到核心網路層之間的佇列,高速網路下如果這個值太小,封包在這個階段就被丟了。

TIME_WAIT 的真相

TIME_WAIT 狀態是很多人第一個想要「解決」的問題,但它存在是有原因的:確保舊連線的延遲封包不會污染新連線。把它完全禁掉或設太激進,在某些情境下會造成資料混淆。

兩個常見的設定:

1
2
net.ipv4.tcp_tw_reuse = 1      # 允許在安全條件下重用 TIME_WAIT socket
net.ipv4.tcp_fin_timeout = 15 # 縮短 FIN_WAIT2 的等待時間

tcp_tw_reuse = 1 相對安全,只對主動發起連線的一側有效,而且只在時間戳(TCP timestamp)啟用的情況下才允許重用。大量對外 HTTP 請求(爬蟲、API client)的伺服器適合開這個。

tcp_tw_recycle 這個參數就不要碰了——它在 Linux 4.12 之後已經被移除,有些舊範本還在寫這個,完全沒意義。

如果 TIME_WAIT 數量持續很高,根本原因通常是短連線太多,解法是改用 keep-alive 或 connection pool,而不是調 TIME_WAIT 相關參數。

本機 Port 範圍

大量對外連線的服務(reverse proxy、爬蟲、API gateway)很容易把本機 ephemeral port 用完:

1
2
3
# 查目前範圍
sysctl net.ipv4.ip_local_port_range
# 預設通常是 32768 60999,也就是約 28000 個 port

調整到更大的範圍:

1
net.ipv4.ip_local_port_range = 1024 65535

這樣可以用的 port 從 ~28000 增加到 ~64000。如果連線速率夠高,TIME_WAIT 的連線還來不及釋放,就直接會看到 connect: Cannot assign requested address。這個報錯不是 DNS 或防火牆問題,是 port 耗盡。

一份可以放心用的基礎設定

整理一份針對一般 Web 服務的基礎設定,放在 /etc/sysctl.d/99-tcp.conf 而不是直接改 /etc/sysctl.conf

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
# 壅塞控制
net.core.default_qdisc = fq
net.ipv4.tcp_congestion_control = bbr

# TCP 緩衝區(適合 RTT 50ms 以上的跨區服務)
net.core.rmem_max = 134217728
net.core.wmem_max = 134217728
net.ipv4.tcp_rmem = 4096 87380 134217728
net.ipv4.tcp_wmem = 4096 65536 134217728

# 連線佇列(高並發 API 服務)
net.core.somaxconn = 65535
net.ipv4.tcp_max_syn_backlog = 65535
net.core.netdev_max_backlog = 250000

# TIME_WAIT
net.ipv4.tcp_tw_reuse = 1
net.ipv4.tcp_fin_timeout = 15
net.ipv4.tcp_max_tw_buckets = 2000000

# Port 範圍
net.ipv4.ip_local_port_range = 1024 65535

套用:

1
sysctl -p /etc/sysctl.d/99-tcp.conf

這份設定適合大多數 Web 和 API 服務的 VPS,但記憶體小於 1GB 的主機要把緩衝區上限拉低(改成 16777216 左右),否則高連線數下記憶體壓力會變高。

調完之後,用 iperf3 做個基準測試,跟調整前的數字對比,才知道有沒有實際效果。


如果你需要一台網路品質穩定、能驗證這些調校效果的 VPS,NCSE Network 提供臺灣是方電訊機房的主機方案,搭配 Intel Gold CPU 和 NVMe SSD,底層網路效能不會是你調校的瓶頸。詳細方案可以到 ncse.tw 查看。

需要高品質的網路服務?

NCSE Network 提供 IP Transit、IP Tunnel 及 BGP 路由規劃,10M~100G 彈性頻寬,多上游備援確保穩定。

了解網路服務 →