今天我们的一个 HAProxy 虚拟机遇到了一点故障转移问题。当我们深入研究它时,我们发现了这个:
1 月 26 日 07:41:45 haproxy2 内核:[226818.070059] __ratelimit:10 个回调被抑制 1 月 26 日 07:41:45 haproxy2 内核:[226818.070064] 套接字内存不足 1 月 26 日 07:41:47 haproxy2 内核:[226819.560048] 套接字内存不足 1 月 26 日 07:41:49 haproxy2 内核:[226822.030044] 套接字内存不足
根据此链接,这显然与net.ipv4.tcp_mem
. 所以我们将它们从默认值增加了 4 倍(这是 Ubuntu 服务器,不确定 Linux 风格是否重要):
当前值为:45984 61312 91968 新值为:183936 245248 367872
之后,我们开始看到一条奇怪的错误消息:
1 月 26 日 08:18:49 haproxy1 内核:[2291.579726] 路由哈希链太长! 1 月 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 实例,谁能建议最好调整哪些路由参数?
我从来没有遇到过这个问题。但是,您可能应该增加哈希表的宽度以减少其深度。使用“dmesg”,您将看到当前有多少条目:
您可以使用内核引导命令行参数更改此值
rhash_entries
。首先手动尝试,然后将其添加到您的lilo.conf
orgrub.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
and中的默认设置tcp_wmem
。默认情况下,每个套接字的输出分配 64 kB,输入分配 87 kB。这意味着代理连接总共需要 300 kB,仅用于套接字缓冲区。再加上 HAProxy 的 16 或 32 kB,您会发现使用 1 GB 的 RAM,您将仅支持 3000 个连接。tcp_rmem
通过更改和(中间参数)的默认设置tcp_wmem
,您可以降低内存。写入缓冲区的值低至 4096,以及tcp_rmem
(5 或 11 个 TCP 段)中的值低至 7300 或 16060,我得到了很好的结果。您可以在不重新启动的情况下更改这些设置,但它们仅适用于新连接。如果您不想过多地接触您的sysctls ,最新的 HAProxy 1.4-dev8 允许您从全局配置和每端(客户端或服务器)调整这些参数。
我希望这会有所帮助!
Out of socket memory error
往往具有误导性。大多数时候,在面向 Internet 的服务器上,它并不表示与内存不足有关的任何问题。正如我在一篇博文中详细解释的那样,最常见的原因是孤立套接字的数量。孤立套接字是与文件描述符无关的套接字。Out of socket memory error
在某些情况下,即使您距离限制 ( ) 有 2 倍或 4 倍,内核也会发出/proc/sys/net/ipv4/tcp_max_orphans
。这在面向 Internet 的服务中经常发生,是完全正常的。在这种情况下,正确的做法是tcp_max_orphans
至少将您在高峰流量时看到的孤儿数量调整为至少 4 倍。不要听任何建议调整的建议,或者
tcp_mem
除非你真的知道你在做什么。那些给出这些建议的人通常不会。他们的巫术通常是错误的或不适合您的环境,并且不会解决您的问题。它甚至可能使情况变得更糟。tcp_rmem
tcp_wmem
我们会定期调整其中一些参数。我们对高吞吐量、低延迟交易平台的标准是: