调整Linux IP路由参数-secret_interval和tcp_mem


30

今天,我们的其中一个HAProxy VM出现了一个小的故障转移问题。当我们对其进行挖掘时,发现了以下内容:

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 Server,不确定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实例,谁能建议最好调整哪些路由参数?

Answers:


28

我从未遇到过这个问题。但是,您可能应该增加哈希表的宽度以减小其深度。使用“ 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的RAM可以分配给TCP套接字。现在,您已经为TCP套接字分配了367872 * 4096字节= 1.5 GB的RAM。您应该非常小心,不要用完内存。经验法则是将1/3的内存分配给HAProxy,再将1/3的内存分配给TCP堆栈,最后1/3的内存分配给系统的其余部分。

我怀疑你的“出槽存储”的消息来自于默认设置tcp_rmemtcp_wmem。默认情况下,每个插座的输出分配了64 kB,输入分配了87 kB。这意味着用于代理连接的总计300 kB,仅用于套接字缓冲区。将HAProxy添加到16或32 kB,您将看到1 GB RAM仅支持3000个连接。

通过改变默认设置tcp_rmemtcp_wmem(中PARAM),就可以得到在内存低了不少。我获得了很好的结果,写缓冲区的值低至4096,而7300或16060 tcp_rmem(5或11个TCP段)。您可以更改这些设置而无需重新启动,但是它们仅适用于新连接。

如果你不喜欢触摸你的sysctl太多,最新的HAProxy的,1.4 DEV8,允许你从全局配置调整这些参数,每方(客户端或服务器)。

我希望这会有所帮助!


8

Out of socket memory error往往是误导。在大多数情况下,在互联网上面向服务器,它并没有指出涉及到内存中运行的任何问题。正如我在博客文章中更详细地解释的那样,最常见的原因是孤立套接字的数量。孤立套接字是不与文件描述符关联的套接字。在某些情况下,Out of socket memory error即使距离极限(/proc/sys/net/ipv4/tcp_max_orphans)2倍或4倍,内核也会发出。这在面向Internet的服务中经常发生,并且完全正常。在这种情况下,正确的做法是将tcp_max_orphans流量调整为至少正常情况下您看到的孤儿数量的4倍。

不要听那个建议调整任何意见tcp_memtcp_rmem或者tcp_wmem,除非你真的知道自己在做什么。那些给出这些建议的人通常不会。他们的伏都教徒通常对您的环境是错误的或不合适的,并且不能解决您的问题。它甚至可能使情况变得更糟。


1
发生这种情况时,消息在dmesg中会有所不同,您会看到“孤立套接字过多”。但是,我同意您的看法,即孤儿会消耗大量内存。
威利·塔罗

当您超过人数时,/proc/sys/net/ipv4/tcp_max_orphans您将遇到另一个错误。例如,整个堆栈交换堆栈的堆栈数为/proc/sys/net/ipv4/tcp_max_orphans65536,/proc/net/sockstat结果为TCP:正在使用2996孤立171 tw 15972分配2998 mem 1621-不能忽略的差异。
杰夫·达尔加斯

-4

我们会定期调整其中一些参数。高吞吐量,低延迟交易平台的标准是:

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

1
根据Willy的数学方法,这意味着您的标准内存压力#(中间数字)为68 GB ?!时间三(rmem,wmem,mem)?
杰夫·阿特伍德

10
这些可调参数是错误的,经常在工作台环境中发现,然后盲目复制粘贴。它们只有几个并发会话不会有任何问题,但是即使有100个TCP套接字,您也将分配3.2 GB的RAM。只要等待时间很短,您就不会发现任何可疑的东西。您只需在传输过程中拔出远程计算机的插头即可查看输出缓冲区的填充,或者冻结本地任务并查看输入缓冲区的填充。这

6
杰夫,这不是三倍。tcp_mem在页面中,并定义全局大小。tcp_rmem和tcp_wmem以字节为单位,并定义每个套接字的大小。
Willy Tarreau,2010年

这些可调参数看起来是错误的,对于并发数据量较小的服务器,您不想保留这么多的套接字缓冲区,而tcp_mem与r / wmem完全不同,使用相同的数字实际上没有任何意义,(一个是每个Connections的字节数,另一个是字节数)每个系统的页面数)
eckes
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.