<b>1.4.2 优化linux下的内核tcp参数以提高系统性能</b>
内核的优化跟服务器的优化一样,应本着稳定安全的原则。下面以squid服务器为例来说明,待客户端与服务器端建立tcp/ip连接后就会关闭socket,服务器端连接的端口状态也就变为time_wait了。那是不是所有执行主动关闭的socket都会进入time_wait状态呢?有没有什么情况可使主动关闭的socket直接进入closed状态呢?答案是主动关闭的一方在发送最后一个ack后就会进入time_wait状态,并停留2msl(报文最大生存)时间,这是tcp/ip必不可少的,也就是说这一点是“解决”不了的。
tcp/ip设计者如此设计,主要原因有两个:
防止上一次连接中的包迷路后重新出现,影响新的连接(经过2msl时间后,上一次连接中所有重复的包都会消失)。
为了可靠地关闭tcp连接。主动关闭方发送的最后一个ack(fin)有可能会丢失,如果丢失,被动方会重新发送fin,这时如果主动方处于 closed状态,就会响应 rst而不是ack。所以主动方要处于time_wait
状态,而不能是closed状态。另外,time_wait 并不会占用很大的资源,除非受到攻击。
在squid服务器中可输入如下命令查看当前连接统计数:
netstat -n | awk
'/^tcp/ {++s[$nf]} end{for(a in s) print a, s[a]}'
命令显示结果如下所示:
last_ack 14
syn_recv 348
established 70
fin_wait1 229
fin_wait2 30
closing 33
time_wait 18122
命令中的含义分别如下。
closed:无活动的或正在进行的连接。
listen:服务器正在等待进入呼叫。
syn_recv:一个连接请求已经到达,等待确认。
syn_sent:应用已经开始,打开一个连接。
established:正常数据传输状态。
fin_wait1:应用说它已经完成。
fin_wait2:另一边已同意释放。
itmed_wait:等待所有分组死掉。
closing:两边尝试同时关闭。
time_wait:另一边已初始化一个释放。
last_ack:等待所有分组死掉。
也就是说,这条命令可以把当前系统的网络连接状态分类汇总。
在linux下高并发的squid服务器中,tcp time_wait套接字的数量经常可达到两三万,服务器很容易就会被拖死。不过,可以通过修改linux内核参数来减少squid服务器的time_wait套接字数量,命令如下:
vim
/etc/sysctl.conf
然后,增加以下参数:
net.ipv4.tcp_fin_timeout
= 30
net.ipv4.tcp_keepalive_time
= 1200
net.ipv4.tcp_syncookies
= 1
net.ipv4.tcp_tw_reuse
net.ipv4.tcp_tw_recycle
net.ipv4.ip_local_port_range
= 10000 65000
net.ipv4.tcp_max_syn_backlog
= 8192
net.ipv4.tcp_max_tw_buckets
= 5000
以下将简单说明上面各个参数的含义:
net.ipv4.tcp_syncookies=1表示开启syn cookies。当出现syn等待队列溢出时,启用cookie来处理,可防范少量的syn攻击。该参数默认为0,表示关闭。
net.ipv4.tcp_tw_reuse=1表示开启重用,即允许将time-wait套接字重新用于新的tcp连接。该参数默认为0,表示关闭。
net.ipv4.tcp_tw_recycle=1表示开启tcp连接中time-wait套接字的快速回收,该参数默认为0,表示关闭。
net.ipv4.tcp_fin_timeout=30表示如果套接字由本端要求关闭,那么这个参数将决定它保持在fin-wait-2状态的时间。
net.ipv4.tcp_keepalive_time=1200表示当keepalived启用时,tcp发送keepalived消息的频度改为20分钟,默认值是2小时。
net.ipv4.ip_local_port_range=10 000 65 000表示centos系统向外连接的端口范围。其默认值很小,这里改为10 000到65 000。建议不要将这里的最低值设得太低,否则可能会占用正常的端口。
net.ipv4.tcp_max_syn_backlog=8192表示syn队列的长度,默认值为1024,此处加大队列长度为8192,可以容纳更多等待连接的网络连接数。
net.ipv4.tcp_max_tw_buckets=5000表示系统同时保持time_wait套接字的最大数量,如果超过这个数字,time_wait套接字将立刻被清除并打印警告信息,默认值为180 000,此处改为5000。对于apache、nginx等服务器,前面介绍的几个参数已经可以很好地减少time_wait套接字的数量,但是对于squid来说,效果却不大,有了此参数就可以控制time_wait套接字的最大数量,避免squid服务器被大量的time_wait套接字拖死。
执行以下命令使内核配置立马生效:
/sbin/sysctl –p
如果是用于apache或nginx等web服务器,则只需要更改以下几项即可:
net.ipv4.tcp_syncookies=1
net.ipv4.tcp_tw_reuse=1
如果是postfix邮件服务器,则建议内核优化方案如下:
= 300
kernel.shmmax =
134217728
当然这些都只是最基本的更改,大家还可以根据自己的需求来更改内核的设置,比如我们的线上机器在高并发的情况下,经常会出现“tcp: too many orpharned sockets”的报错尽量也要本着服务器稳定的最高原则。如果服务器不稳定的话,一切工作和努力就都会白费。如果以上优化仍无法满足工作要求,则有可能需要定制你的服务器内核或升级服务器硬件。