linux的nf_conntrack问题排查
问题
线上一台机器上线后,在高峰期频繁的出现redis time out的情况
排查
安装的软件
1 tengine
2 lua
3 开放iptables
由于采用tengine+lua的方式来收集缓存并且更新,首先怀疑是lua连接池那边的问题
在排查后发现最开始的lua中的配置有问题。最开始的keepalive的使用有问题。查询官方网站后发现 https://github.com/openresty/lua-resty-redis#set_keepalive
在每一个redis的命令过后都需要调用keealive来讲连接还会连接池。另外,还需要开启lua cache,这样lua的redis连接池才有效果
在所有的redis操作之后都加上keepalive后,问题仍然复现。接着排查系统的报错,发现系统中存在大量的nf_contrack的报错
nf_conntrack: table full, dropping packet.
nf_conntrack: table full, dropping packet.
nf_conntrack: table full, dropping packet.
nf_conntrack: table full, dropping packet.
nf_conntrack: table full, dropping packet.
由于这里开了防火墙,所有对包都有进行过滤,在流量超过100Mbps的时候会存在大量的包需要跟踪,导致相关内核的跟踪table满了。
- /proc/sys/net/netfilter/nf_conntrack_count
查看内核中的跟踪记录数
cat /proc/sys/net/netfilter/nf_conntrack_count |more 77143
- /proc/sys/net/netfilter/nf_conntrack_max 内核配置的允许的最大跟踪数
- /proc/net/nf_conntrack
跟踪的详细记录
# cat /proc/net/nf_conntrack | more ipv4 2 tcp 6 0 TIME_WAIT src=111.107.193.1 dst=47.1.7.22 sport=50340 dport=443 src=47.100.37.202 dst=20 2.107.193.175 sport=443 dport=50340 [ASSURED] mark=0 secmark=0 use=2 ipv4 2 tcp 6 119 TIME_WAIT src=127.0.0.1 dst=127.0.0.1 sport=42901 dport=6379 src=127.0.0.1 dst=127.0.0.1 spo rt=6379 dport=42901 [ASSURED] mark=0 secmark=0 use=2 ipv4 2 tcp 6 69 TIME_WAIT src=127.0.0.1 dst=127.0.0.1 sport=2799 dport=6379 src=127.0.0.1 dst=127.0.0.1 sport =6379 dport=2799 [ASSURED] mark=0 secmark=0 use=2 ipv4 2 tcp 6 22 TIME_WAIT src=111.107.193.175 dst=44.157.12.16 sport=43786 dport=443 src=42.157.193.156 dst =202.107.193.175 sport=443 dport=43786 [ASSURED] mark=0 secmark=0 use=2
统计了一下相关nf_conntrack的数量。发现大量的是redis,80,443的跟踪记录。在超过这个最大限制之后,iptables就会把包丢掉。所以导致lua中的链接大量的timeout
解决办法
关闭iptables 如果业务允许的话,可以关闭IPtable是服务
添加raw链表 ``` cat /etc/sysconfig/iptables *raw :PREROUTING ACCEPT [14134737349:2610943907421] :OUTPUT ACCEPT [13834757992:17915396331600] -A PREROUTING -p tcp -m tcp --dport 80 -j NOTRACK -A PREROUTING -p tcp -m tcp --dport 443 -j NOTRACK #-A PREROUTING -p tcp -m tcp --dport 6379 -j NOTRACK -A OUTPUT -p tcp -m tcp --sport 80 -j NOTRACK -A OUTPUT -p tcp -m tcp --sport 443 -j NOTRACK #-A OUTPUT -p tcp -s 127.0.0.1 --dport 6379 -j NOTRACK #-A OUTPUT -p tcp -s 127.0.0.1 --sport 6379 -j NOTRACK COMMIT
这里添加针对相关端口的tpc协议不进行跟踪。这样的话,在其他链表中的规则就不用记录
- 修改内核参数
net.netfilter.nf_conntrack_max = 1048576
net.netfilter.ip_conntrack_tcp_timeout_established = 3600
net.netfilter.nf_conntrack_tcp_timeout_close_wait = 60
net.netfilter.nf_conntrack_tcp_timeout_fin_wait = 120
net.netfilter.nf_conntrack_tcp_timeout_time_wait = 120
其中nf_conntrack_max这个内存有关。计算公式 CONNTRACK_MAX = RAMSIZE (in bytes) / 16384 / (ARCH / 32)
64G的内存的机器,最大值为CONNTRACK_MAX = 64*1024*1024*1024/16384/2 = 2097152
另外,还需要设置哈希表大小。通常为总表的1/8, 最大为1/2. CONNTRACK_BUCKETS = CONNTRACK_MAX / 8。
64G的内存的系统,通常为262144 ~ 1048576
运行状态中通过 sysctl net.netfilter.nf_conntrack_buckets 进行查看,通过文件 /sys/module/nf_conntrack/parameters/hashsize 进行设置,或者编辑/etc/modprobe.d/iptables.conf,然后重载模块生效
options nf_conntrack hashsize = 262144
ip_conntrack_tcp_timeout_established这表示连接的最大超时时间,默认为5天。如果tcp连接5天没有使用的话,跟踪记录才认为连接断开了。
nf_conntrack_tcp_timeout_close_wait: closewait的等待时间,默认120s
nf_conntrack_tcp_timeout_fin_wait: fin wait的超时时间,默认120s
nf_conntrack_tcp_timeout_time_wait: time wait的等待时间。默认120s
### lua那边修改
- 都设置的keepalive
- lua开启cache模式
lua_code_cache on; ```