高并发下内核netfilter模块conntrack表full的处理方案

最近发现Tracker所在的BuyVM服务器意外重启,于是调查重启原因时发现系统日志中持续出现大量的如下提示信息。

July 23 08:29:57 localhost kernel: [345379.839795] nf_conntrack: nf_conntrack: table full, dropping packet
July 23 08:29:57 localhost kernel: [345379.841751] nf_conntrack: nf_conntrack: table full, dropping packet
July 23 08:29:57 localhost kernel: [345379.848711] nf_conntrack: nf_conntrack: table full, dropping packet
July 23 08:29:57 localhost kernel: [345379.851790] nf_conntrack: nf_conntrack: table full, dropping packet
July 23 08:29:57 localhost kernel: [345379.864515] nf_conntrack: nf_conntrack: table full, dropping packet

才注意到TCP会话数超出了系统配置的最大值,然后开始丢包。由于Tracker服务器目前服务全网请求量确实很大,内核netfilter模块conntrack默认参数配置过低,导致新连接被drop掉。

查阅了资料后,发现nf_conntrack模块在Linux Kernel 2.6.15 被引入,同时支持IPV4和IPV6,取代只支持IPV4的ip_connktrack,主要用来跟踪连接的状态,以供其他模块使用,例如用于NAT和连接状态记录。
nf_conntrack用一个哈希表记录已建立的连接,包括其他机器到本机、本机到其他机器、本机内部的连接,如果连接进来比释放得快,把这个哈希表塞满了,新连接的数据包会被drop掉,此时netfilter变成了一个黑洞,导致拒绝服务,就像上面看到的结果。

和 nf_conntrack 相关的内核参数可以用下面的命令查看

sysctl -a | grep conntrack

nf_conntrack_buckets 使用情况查看

grep conntrack /proc/slabinfo

前四个数字分别为:当前活动对象数、可用对象总数、每个对象的大小(字节)、包含至少1个活动对象的分页数。

查看nf_conntrack表最大连接数

cat /proc/sys/net/netfilter/nf_conntrack_max

查看nf_conntrack_buckets哈希表最大大小

cat /proc/sys/net/netfilter/nf_conntrack_buckets

此时会发现两个值几乎相近(当然最大连接数必定略小于哈希表最大大小,毕竟多出来的都被drop了)。

那既然最大连接数过小,那么调大就好了。

注意一下 net.netfilter.nf_conntrack_max 不是越高越好,通常根据内存大小进行设置。一般来说网上通用的计算公式如下:

nf_conntrack_max计算公式(64位)
CONNTRACK_MAX = RAMSIZE (inbytes)/16384/2

例如你的机器是一个64GB 64bit的系统,那么最合适的值是
CONNTRACK_MAX = 64*1024*1024*1024/16384/2 = 2097152

nf_conntrack_buckets决定存储conntrack条目的哈希表大小,默认值是nf_conntrack_max的1/4,延续这种计算方式:BUCKETS = CONNTRACK_MAX/4,如64G内存可以设置524288,此时哈希表也可修改一下。

但是我算了下结果,貌似和我当前的默认值一样,因此索性把值提了一倍。

修改方法如下:

执行以下命令,使配置即时生效。(注意这里的两个值要根据实际修改一下)

sysctl -w net.netfilter.nf_conntrack_max=2097152

修改哈希表大小

echo 524288 > /sys/module/nf_conntrack/parameters/hashsize

执行以下命令可确保重启后配置仍然生效。

echo "net.netfilter.nf_conntrack_max = 2097152" >> /etc/sysctl.conf

可以顺便修改一下tcp_timeout_established,默认值长达五天之久。

echo "net.netfilter.nf_conntrack_tcp_timeout_established = 3600" >> /etc/sysctl.conf

修改后连接就不会被drop了。实际上如果云服务厂商有提供安全组、防火墙等功能,可以直接使用外部防火墙,此时可以直接撤掉机器内部的防火墙,也就没有这个问题了。亦或者如果不需要使用到涉及到状态链路相关或者NAT相关的应用,也可以直接设置不加载这个模块的。

暂无评论

发送评论 编辑评论


|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇
下一篇