现象:
服务器产生大量SYN_RECV连接,而系统默认SYN_RECV为1024,如果系统当前的syn_recv达到系统默认值,Nginx会不处理新来的连接,导致影响业务。
分析:
目前是使用f5的layer4模式转发请求,故所有tcp连接的处理都在服务器端完成,有可能是网络质量不好而导致产生大量的syn_recv,使用netstat命令查看TOP 10 syn_recv ip,发现都是移动网关过来的,初步判断可能是移动网络慢对方无法接受服务器返回的包而产生syn_recv,尤其是如下ip比较明显:211.139.92.11(甘肃省兰州市移动)。
解决方法:
1.F5改为standard方式,所有tcp连接由F5处理,后端只关注业务,故障解决,但 加大F5的性能负荷。
2.服务器修改内核,使其能容纳更多的syn_recv,加大网络连接;
修改内核参数如下:
1)net.ipv4.tcp_max_syn_backlog = 65536
该参数是SYN队列的长度,默认为1024,修改为65536,加大SYN队列长度可以容纳更多等待连接的网络连接数
2)net.core.netdev_max_backlog = 32768
该参数决定了,网络设备接收数据包的速率比内核处理这些包的速率快时,允许送到队列的数据包的最大数目,默认值为300。根据需要调整改值,不要设置的过大。
3)net.core.somaxconn = 32768
该参数用来限制监听队列最大数据包的数量,超过这个数量就会导致链接超时或者触发重传机制。
也就是说
,web
应用中
listen
函数的
backlog
会给我们内核参数的
net.core.somaxconn
限制到
128,
在高突发的请求中可能会导致链接超时或者触发重传;例如:
nginx的默认的backlog队列为511,如果内核参数net.core.somaxconn的值低于511,那么nginx的backlog队列将被限制为该参数的值。此外,可以在nginx的配置中增加监听队列的数量,当然前提是不能超过net.core.somaxconn的值。
server {
listen 80 deafult backlog=8192;
server_name http://www.libertyvps.com]www.libertyvps.com;
}
4)net.ipv4.tcp_syncookies = 1
该参数是一个开关,是否打开SYN Cookie功能,该功能可以防止部分SYN攻击,默认为0关闭,1开启。
注意:该选项千万不能用于那些没有收到攻击的高负载服务器,如果在日志中出现synflood消息,但是调查发现没有收到synflood攻击,而是合法用户的连接负载过高的原因,你应该调整其它参数来提高服务器性能。参考:
5)net.ipv4.tcp_synack_retries = 0
默认值是5,对于远端的连接请求SYN,内核会发送SYN + ACK数据报,以确认收到上一个 SYN连接请求包。这是所谓的三次握手( threeway handshake)机制的第二个步骤。这里决定内核在放弃连接之前所送出的 SYN+ACK 数目。不应该大于255,默认值是5,对应于180秒左右时间。(可以根据下面的 tcp_syn_retries 来决定这个值)
6)net.ipv4.tcp_syn_retries = 0
默认值是5,对于一个新建连接,内核要发送多少个 SYN 连接请求才决定放弃。不应该大于255,默认值是5,对应于180秒左右时间。(对于大负载而物理通信良好的网络而言,这个值偏高,可修改为2.这个值仅仅是针对对外的连接,对进来的连接,是由tcp_retries1 决定的)
注:5)6)这2项可根据业务的特性灵活调整,我这里设置为0,对业务本身没有很大的影响,查看连接及日志没有减少的变化。
7)由于我们的业务是移动互联网业务,根据其特殊性,如修改了如下2个参数,会对业务有一定影响,请不要调整,保持默认即可。
net.ipv4.tcp_rw_reuse = 0
net.ipv4.tcp_rw_recycle = 0
通过查看服务器,有大量的TIME_WAIT连接,而很多是出现在nginx+php-cgi的ip转发连接方式,建议可调整为通过unix socket方式访问,减少不必要的网络消耗。
经过以上调整,服务器在容纳更多的SYN_RECV亦保证nginx能正常提供web访问,查看系统负载,保持在1以下。