当前位置:首页 > 运维 > 正文内容

linux中nf_conntrack table full dropping packet问题处理

phpmianshi5年前 (2016-04-16)运维131

概述:


在日常的服务器运维过程中,发现某段时间 /var/log/messages日志报错
nf_conntrack:table full,drop packet

简介:

nf_conntrack是内核模块中的连接追踪模块。与iptables有关。用于跟踪一个连接状态。连接跟踪状态可以供其他模块使用,例如state等,可通过以下查看

[root@VM_0_11_centos vhost]#          lsmod |egrep conntrack
nf_conntrack_ipv4      15053  0
nf_defrag_ipv4         12729  1 nf_conntrack_ipv4
nf_conntrack          133053  1 nf_conntrack_ipv4
libcrc32c              12644  2 sctp,nf_conntrac

# 查看nf_conntrack表最大连接数
[root@VM_0_11_centos vhost]# cat /proc/sys/net/netfilter/nf_conntrack_max
6553500
# 查看nf_conntrack表当前连接数
[root@VM_0_11_centos vhost]# cat /proc/sys/net/netfilter/nf_conntrack_count
114

查出目前 nf_conntrack 的排名:
[root@VM_0_11_centos vhost]# cat /proc/net/nf_conntrack |awk '{print $11}' |cut -d '=' -f 2 | sort |uniq -c | sort -nr | head -n 10
     55 169.254.0.4
     31 172.16.0.11
      1 169.254.0.55
      1 169.254.0.15
      1 0

当有大量的网站访问时,若iptables记录连接跟踪状态,就可能导出现“nf_conntrack:table full”,从而导致一系列问题。

像php-fpm这种提供web短连接服务的项目,server端主动断开连接成功就会有个2MLS的time_wait,这些连接也都被track,该conntrack也会占用2分钟的时间。

这都不用并发太高的环境,比如每秒并发个100,2MLS的时间2分钟得生成2x60x100=12000,生成1万多的time_wait记录。这里就是个短连接不断积累的过程,不断地server主动断开,不断地timewait,这些都会被conntrack跟踪记录。所以一般默认的nf_conntrack_max=65535,很快就被塞满了。一旦塞满了就会随机的drop包。在外面看来就是丢包情况非常厉害。


解决方案:


1.优化参数

nf_conntrack_max决定连接跟踪表的大小,默认值是65535,理论最大值官方有个计算公式

CONNTRACK_MAX = RAMSIZE (in bytes) / 16384 / (ARCH / 32)
以16G的64位操作系统为例,CONNTRACK_MAX = 16*1024*1024*1024/16384/2 = 524288

nf_conntrack_buckets决定存储conntrack条目的哈希表大小,其哈希表大小通常为总表的1/8,最大为1/2。默认值是nf_conntrack_max的1/4  

CONNTRACK_BUCKETS = CONNTRACK_MAX / 4
同样64G的64位操作系统,哈希最佳范围是 65536 ~ 262144 。
运行状态中通过 sysctl net.netfilter.nf_conntrack_buckets 进行查看

旧版本修改: echo 262144 >  /sys/module/nf_conntrack/parameters/hashsize 进行设置

4.9内核下能直接修改 /proc/sys/net/netfilter/nf_conntrack_buckets


nf_conntrack_tcp_timeout_established决定ESTABLISHED状态连接的超时时间,默认值是5天,可以缩短到1小时,即3600。

还有些相关的系统参数`sysctl -a | grep nf_conntrack`可以调优(/etc/sysctl.conf ): 

vim /etc/sysctl.conf
#加大 ip_conntrack_max 值
net.nf_conntrack_max = 524288

net.netfilter.nf_conntrack_max = 524288

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
net.netfilter.nf_conntrack_tcp_timeout_established = 3600

增加完以上内容后,通过sysctl -p 使配置生效 。不过该方法缺点:一是重启iptables后,ip_conntrack_max值又会变成65535默认值,需要重新sysctl -p


2.移除模块

modprobe -r xt_NOTRACK nf_conntrack_netbios_ns nf_conntrack_ipv4 xt_state
modprobe -r nf_conntrack

执行完查看/proc/net/ 下面如果没用了 nf_conntrack ,就证明模块移除成功了

注意: 此方法会将state模块也一块儿移除掉,如果我们的iptables应用nat会用到state模块,卸载后导致iptables某些功能无法使用。


3.使用raw表,跳过跟踪记录。

首先先认识下什么是raw表?做什么用的?

iptables有5个链:PREROUTING,INPUT,FORWARD,OUTPUT,POSTROUTING,4个表:filter,nat,mangle,raw 。

4个表的优先级由高到低的顺序为:raw–>mangle–>nat–>filter

举例来说:如果PRROUTING链上,即有mangle表,也有nat表,那么先由mangle处理,然后由nat表处理 。

RAW表只使用在PREROUTING链和OUTPUT链上,因为优先级最高,从而可以对收到的数据包在连接跟踪前进行处理。一但用户使用了RAW表,在某个链上,RAW表处理完后,将跳过NAT表和 ip_conntrack处理,即不再做地址转换和数据包的链接跟踪处理了。
RAW表可以应用在那些不需要做nat的情况下,以提高性能。如大量访问的web服务器,可以让80端口不再让iptables做数据包的链接跟踪处理,以提高用户的访问速度 。

使用方法:
(1)改/etc/sysconfig/iptables 文件中的-A INPUT -m state –state RELATED,ESTABLISHED, UNTRACKED -j ACCEPT 行。增加”UNTRACKED”,保存并restart iptables
注意: 必须更改此步,增加”UNTRACKED“,否则执行后面的语句会造成相应的端口不能访问。我使用该方法时就因为没有执行第一步的操作,造成web访问不能使用。
(2)增加以下语句

# 针对进入本机的包
/sbin/iptables -t raw -A PREROUTING -p tcp -m multiport --dports 80 -j NOTRACK
# 针对从本机出去的包
/sbin/iptables -t raw -A OUTPUT  -p tcp -m multiport --sports 80 -j NOTRACK
/sbin/iptables -t raw -A PREROUTING -i lo -j NOTRACK
/sbin/iptables -t raw -A OUTPUT  -o lo -j NOTRACK

注意: 一定将进入和出去的包都设置规则。这样的好处是治本,把不需要track的iptables直接notrack,那自然就不会去占hashtable空间了,更不会报错了。


版权声明:本文由PHP面试资料网发布,如需转载请注明出处。
分享给朋友:

相关文章

输入一个URL到底发生了什么

输入一个URL到底发生了什么

DNS解析TCP连接发送http请求服务器处理请求浏览器解析渲染页面连接结束DNS解析根域名服务器(root Name server) 是互联网域名解析系统(DNS)中最高级别的域名服务器,负责返...






TCP(Transmission Control Protocol) 传输控制协议

三次握手

TCP是主机对主机层的传输控制协议,提供可靠的连接服务,采用三次握手确认建立一个连接:

位码即tcp标志位,有6种标示:

SYN(synchronous建立联机) 同步报文段

ACK(acknowledgement 确认)

PSH(push传送)

FIN(finish结束) 结束报文段

RST(reset重置) 复位报文段

URG(urgent紧急) 紧急指针

Sequence number(顺序号码)

Acknowledge number(确认号码)

客户端TCP状态迁移:

CLOSED->SYN_SENT->ESTABLISHED->FIN_WAIT_1->FIN_WAIT_2->TIME_WAIT->CLOSED

服务器TCP状态迁移:

CLOSED->LISTEN->SYN收到->ESTABLISHED->CLOSE_WAIT->LAST_ACK->CLOSED


各个状态的意义如下: 

LISTEN - 侦听来自远方TCP端口的连接请求; 

SYN-SENT -在发送连接请求后等待匹配的连接请求; 

SYN-RECEIVED - 在收到和发送一个连接请求后等待对连接请求的确认; 

ESTABLISHED- 代表一个打开的连接,数据可以传送给用户; 

FIN-WAIT-1 - 等待远程TCP的连接中断请求,或先前的连接中断请求的确认;

FIN-WAIT-2 - 从远程TCP等待连接中断请求; 

CLOSE-WAIT - 等待从本地用户发来的连接中断请求; 

CLOSING -等待远程TCP对连接中断的确认; 

LAST-ACK - 等待原来发向远程TCP的连接中断请求的确认; 

TIME-WAIT -等待足够的时间以确保远程TCP接收到连接中断请求的确认; 

CLOSED - 没有任何连接状态;


TCP/IP协议中,TCP协议提供可靠的连接服务,采用三次握手建立一个连接,如图1所示。

(1)第一次握手:建立连接时,客户端A发送SYN包(SYN=j)到服务器B,并进入SYN_SEND状态,等待服务器B确认。

(2)第二次握手:服务器B收到SYN包,必须确认客户A的SYN(ACK=j+1),同时自己也发送一个SYN包(SYN=k),即SYN+ACK包,此时服务器B进入SYN_RECV状态。

(3)第三次握手:客户端A收到服务器B的SYN+ACK包,向服务器B发送确认包ACK(ACK=k+1),此包发送完毕,客户端A和服务器B进入ESTABLISHED状态,完成三次握手。

完成三次握手,客户端与服务器开始传送数据。

确认号:其数值等于发送方的发送序号 +1(即接收方期望接收的下一个序列号)。

图1 TCP三次握手建立连接  


TCP协议中的三次握手和四次挥手

理解:窗口和滑动窗口TCP的流量控制TCP使用窗口机制进行流量控制什么是窗口?连接建立时,各端分配一块缓冲区用来存储接收的数据,并将缓冲区的尺寸发送给另一端接收方发送的确认信息中包含了自己剩余的缓冲区...

Nginx中last和break redirect和permanent区别和联系

一.last & break    (1)last 和 break 当出现在location 之外时,两者的作用是一致的没有任何差异。注意一点就是,他们会跳过所有的在他们之...

linux中tcpdump的详细用法

linux中tcpdump的详细用法

在调试网络通信程序是tcpdump是必备工具。tcpdump很强大,可以看到网络通信的每个细节。如TCP,可以看到3次握手,PUSH/ACK数据推送,close4次挥手,全部细节。包括每一次网络收包的...

负载均衡工作模式以及工作原理

负载均衡的多种解决方案:HTTP重定向当用户发来请求的时候,Web服务器通过修改HTTP响应头中的Location标记来返回一个新的url,然后浏览器再继续请求这个新url,实际上就是页面重定向。通过...


1、应用程序中调用read() 方法,这里会涉及到一次上下文切换(用户态->内核态),底层采用DMA(direct memory access)读取磁盘的文件,并把内容存储到内核地址空间的读取缓存区。

2、由于应用程序无法读取内核地址空间的数据,如果应用程序要操作这些数据,必须把这些内容从读取缓冲区拷贝到用户缓冲区。这个时候,read() 调用返回,且引发一次上下文切换(内核态->用户态),现在数据已经被拷贝到了用户地址空间缓冲区,这时,如果有需要,应用程序可以操作修改这些内容。

3、我们最终目的是把这个文件内容通过Socket传到另一个服务中,调用Socket的send()方法,这里又涉及到一次上下文切换(用户态->内核态),同时,文件内容被进行第三次拷贝,被再次拷贝到内核地址空间缓冲区,但是这次的缓冲区与目标套接字相关联,与读取缓冲区没有半点关系。

4、send()调用返回,引发第四次的上下文切换,同时进行第四次的数据拷贝,通过DMA把数据从目标套接字相关的缓存区传到协议引擎进行发送。

"在整个过程中,过程1和4是由DMA负责,并不会消耗CPU,只有过程2和3的拷贝需要CPU参与


如果在应用程序中,不需要操作内容,过程2和3就是多余的,如果可以直接把内核态读取缓存冲区数据直接拷贝到套接字相关的缓存区,是不是可以达到优化的目的?

Linux中nio的实现原理

我们上一篇文章 《linux中netstat和ss命令详解》中提到了nio 原文:https://phpmianshi.com/?id=105有一些小伙伴私信想了解什么是nio,我们这篇详细介绍下什么...

发表评论

访客

◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。