今天,我們的一台 HAProxy 虛擬機器遇到了一點故障轉移問題。當我們深入研究時,我們發現了這一點:
Jan 26 07:41:45 haproxy2 核心:[226818.070059] __ratelimit:抑制 10 個回調 Jan 26 07:41:45 haproxy2 核心:[226818.070064] 套接字記憶體不足 Jan 26 07:41:47 haproxy2 核心:[226819.560048] 套接字記憶體不足 Jan 26 07:41:49 haproxy2 核心:[226822.030044] 套接字記憶體不足
其中,每這個連結,顯然與 的預設值較低有關net.ipv4.tcp_mem
。因此我們將它們從預設值增加了 4 倍(這是 Ubuntu Server,不確定 Linux 風格是否重要):
目前值為: 45984 61312 91968 新值為:183936 245248 367872
之後,我們開始看到一條奇怪的錯誤訊息:
Jan 26 08:18:49 haproxy1 核心:[2291.579726] 路由雜湊鏈太長! Jan 26 08:18:49 haproxy1 核心:[2291.579732]調整你的secret_interval!
噓..這是一個秘密!
/proc/sys/net/ipv4/route/secret_interval
這顯然與預設值 600 和控制項有關定期刷新路由快取
指示
secret_interval
核心多久清除一次所有路由雜湊條目,無論它們有多新/舊。在我們的環境中,這通常很糟糕。每次清除快取時,CPU 都會忙於每秒重建數千個條目。然而,我們將其設定為每天運行一次,以防止記憶體洩漏(儘管我們從未發生過)。
雖然我們很樂意減少這種情況,建議定期刪除整個路由快取似乎很奇怪,而不是簡單地將舊值更快地從路由快取中推出。
經過一番調查後,我們發現/proc/sys/net/ipv4/route/gc_elasticity
這似乎是控制路由表大小的更好選擇:
gc_elasticity
可以最好地描述為核心在路由雜湊條目開始過期之前將接受的平均儲存桶深度。這將有助於維持活動路由的上限。
我們將彈性從 8 調整為 4,希望路由快取能夠更積極地自行修剪。我們secret_interval
感覺不正確。但有很多設置,目前還不清楚哪些才是正確的設置方式。
- /proc/sys/net/ipv4/route/gc_elasticity (8)
- /proc/sys/net/ipv4/route/gc_interval (60)
- /proc/sys/net/ipv4/route/gc_min_interval (0)
- /proc/sys/net/ipv4/route/gc_timeout (300)
- /proc/sys/net/ipv4/route/secret_interval (600)
- /proc/sys/net/ipv4/route/gc_thresh(?)
- rhash_entries(核心參數,預設未知?)
我們不想讓Linux路由更差,所以我們有點害怕弄亂其中一些設定。
對於高流量 HAProxy 實例,誰能建議最好調整哪些路由參數?
答案1
我從來沒有遇到過這個問題。但是,您可能應該增加哈希表的寬度以減少其深度。使用“dmesg”,您將看到目前有多少條目:
$ dmesg | grep '^IP route'
IP route cache hash table entries: 32768 (order: 5, 131072 bytes)
您可以使用核心引導命令列參數來變更此值rhash_entries
。首先手動嘗試,然後將其添加到您的lilo.conf
或grub.conf
.
例如:kernel vmlinux rhash_entries=131072
您的哈希表可能非常有限,因為您為 HAProxy VM 分配的記憶體很少(路由哈希大小根據總 RAM 進行調整)。
說到這裡tcp_mem
,要小心。您的初始設定讓我認為您正在使用 1 GB RAM 運行,其中 1/3 可以分配給 TCP 套接字。現在您已為 TCP 套接字分配了 367872 * 4096 位元組 = 1.5 GB RAM。您應該非常小心,不要耗盡內存。經驗法則是將 1/3 的記憶體分配給 HAProxy,另外 1/3 分配給 TCP 堆疊,最後 1/3 分配給系統的其餘部分。
我懷疑您的“插座內存不足”訊息來自 和 中的預設tcp_rmem
設定tcp_wmem
。預設情況下,每個套接字的輸出分配有 64 kB,輸入分配有 87 kB。這表示代理連線總共需要 300 kB,僅用於套接字緩衝區。再加上 HAProxy 的 16 或 32 kB,您會發現使用 1 GB RAM 只能支援 3000 個連線。
tcp_rmem
透過更改和(中間參數)的預設設置tcp_wmem
,您可以大幅減少記憶體佔用。我得到了良好的結果,寫入緩衝區的值低至 4096,而寫入緩衝區的值低至 7300 或 16060 tcp_rmem
(5 或 11 個 TCP 段)。您可以更改這些設定而無需重新啟動,但它們僅適用於新連接。
如果您不想碰觸您的系統指令太多了,最新的 HAProxy 1.4-dev8 允許您從全域配置和每端(客戶端或伺服器)調整這些參數。
我希望這有幫助!
答案2
這Out of socket memory error
常常具有誤導性。大多數時候,在面向互聯網的伺服器上,它確實如此不是指示與記憶體不足相關的任何問題。正如我在中更詳細地解釋的那樣一篇博文,最常見的原因是孤兒套接字的數量。孤立套接字是不與檔案描述符關聯的套接字。在某些情況下,Out of socket memory error
即使您距離限制 ( ) 的距離是 2 倍或 4 倍,內核也會發出/proc/sys/net/ipv4/tcp_max_orphans
。這種情況在面向互聯網的服務中經常發生,而且是完全正常的。在這種情況下,正確的做法是將tcp_max_orphans
孤兒數量調整為您通常在峰值流量中看到的至少 4 倍。
不要聽取任何建議調整的建議tcp_mem
,或tcp_rmem
除非tcp_wmem
您真的知道你在做什麼。那些提出這些建議的人通常不會這樣做。他們的巫術通常是錯誤的或不適合您的環境,並且不會解決您的問題。它甚至可能使情況變得更糟。
答案3
我們定期調整其中一些參數。我們的高吞吐量、低延遲交易平台的標準是:
net.ipv4.tcp_rmem = 4096 16777216 33554432 net.ipv4.tcp_wmem = 4096 16777216 33554432 net.ipv4.tcp_mem = 4096 16777216 33554432 net.core.rmem_default = 16777216 net.core.wmem_default = 16777216 net.core.rmem_max=16777216 net.core.wmem_max=16777216 net.core.netdev_max_backlog = 30000 net.core.netdev_max_backlog = 30000