Linux

什麼限制了 Linux 伺服器上的最大連接數?

  • August 28, 2017

哪些核心參數或其他設置控制 Linux 伺服器上可以打開的 TCP 套接字的最大數量?允許更多連接的權衡是什麼?

我注意到在使用ab對 Apache 伺服器進行負載測試時,很容易將伺服器上的打開連接最大化。如果您不使用允許連接重用的 ab 的 -k 選項,並讓它發送超過 10,000 個請求,那麼 Apache 會處理前 11,000 個左右的請求,然後停止 60 秒。查看 netstat 輸出顯示 11,000 個連接處於 TIME_WAIT 狀態。顯然,這是正常的。出於TCP 可靠性的原因,即使在客戶端完成連接後,連接仍會保持預設打開 60 秒。

看起來這將是一種對伺服器進行 DoS 的簡單方法,我想知道通常的調整和預防措施是什麼。

這是我的測試輸出:

# ab -c 5 -n 50000 http://localhost/
This is ApacheBench, Version 2.0.40-dev <$Revision: 1.146 $> apache-2.0
Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/
Copyright 2006 The Apache Software Foundation, http://www.apache.org/

Benchmarking localhost (be patient)
Completed 5000 requests
Completed 10000 requests
apr_poll: The timeout specified has expired (70007)
Total of 11655 requests completed

這是我在測試期間執行的 netstat 命令:

# netstat --inet -p | grep "localhost:www" | sed -e 's/ \+/ /g' | cut -d' ' -f 1-4,6-7 | sort | uniq -c 
 11651 tcp 0 0 localhost:www TIME_WAIT -
     1 tcp 0 1 localhost:44423 SYN_SENT 7831/ab
     1 tcp 0 1 localhost:44424 SYN_SENT 7831/ab
     1 tcp 0 1 localhost:44425 SYN_SENT 7831/ab
     1 tcp 0 1 localhost:44426 SYN_SENT 7831/ab
     1 tcp 0 1 localhost:44428 SYN_SENT 7831/ab

我終於找到了真正限制連接數的設置:net.ipv4.netfilter.ip_conntrack_max. 這被設置為 11,776,無論我設置什麼,都是我可以在測試中服務的請求數,然後必須等待tcp_fin_timeout幾秒鐘才能獲得更多連接。該conntrack表是核心用來跟踪連接狀態的表,因此一旦它已滿,核心就會開始丟棄數據包並將其列印在日誌中:

Jun  2 20:39:14 XXXX-XXX kernel: ip_conntrack: table full, dropping packet.

下一步是讓核心回收所有處於該TIME_WAIT狀態的連接,而不是丟棄數據包。我可以通過打開tcp_tw_recycle或增加到ip_conntrack_max大於可用於連接的本地埠數來實現這一點ip_local_port_range。我想一旦核心離開本地埠,它就會開始回收連接。這使用了更多的記憶體跟踪連接,但它似乎比打開更好的解決方案,tcp_tw_recycle因為文件暗示這是危險的。

使用此配置,我可以整天執行 ab 並且永遠不會用完連接:

net.ipv4.netfilter.ip_conntrack_max = 32768
net.ipv4.tcp_tw_recycle = 0
net.ipv4.tcp_tw_reuse = 0
net.ipv4.tcp_orphan_retries = 1
net.ipv4.tcp_fin_timeout = 25
net.ipv4.tcp_max_orphans = 8192
net.ipv4.ip_local_port_range = 32768    61000

tcp_max_orphans設置對我的測試沒有任何影響,我不知道為什麼。我認為TIME_WAIT一旦有 8192 個連接,它就會關閉 state 中的連接,但它對我來說並沒有這樣做。

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