什麼限制了 Linux 伺服器上的最大連接數?
哪些核心參數或其他設置控制 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 中的連接,但它對我來說並沒有這樣做。