linux tcp/ip内核参数分析与调优[原创]--http://www.22455.com/index.php

inux tcp/ip内核参数分析与调优[原创]

先贴一个生产环境下5000连接Nginx的运行服务器的连接状态:

01 [root@weba ~]# netstat -na |awk '{print $6}'| sort |uniq -c |sort -nr
02    4963 ESTABLISHED  port80
03     706 FIN_WAIT1    port80
04     134 TIME_WAIT    port80
05      74 CONNECTED       
06      41
07      33 LISTEN
08      25 LAST_ACK
09      18 SYN_RECV
10      12 STREAM
11       1 I-Node
12       1 Foreign
13       1 FIN_WAIT2

放一张图,要搞清楚怎么调整参数,这张图相当重要。看不太明白不要紧,后面会详细讲到这张图

 

三次握手以及其中的各种状态:

 

SYN(Synchronize Sequence Numbers)。

同步序列编号

ACK (ACKnowledge Character)

在数据通信传输中,接收站发给发送站的一种传输控制字符。它表示确认发来的数据已经接受无误。


=================================

client发送syn至server

此时客户端的状态变为SYN_SENT

client(syn=j)====>server

server收到syn,并发送syn+ack到client,

这种过程server状态由listen变为SYN_RECV,并等待客户端再次发来ack数据

client<=========server(syn=k,ack=j+1)

client接收到server发过来的syn+ack,并向服务端发送ACK,服务器接收后由SYN_RECV变为ESTABLISHED

client(ACK(ack=k+1))========>server

此种情况下,服务端在三次握手的变迁是

LISTEN->SYN_RECV ->ESTABLISHED

客户端的三次握手的变迁是

SYN_SENT ->ESTABLISHED

====================================

在这种过程中要注意的

一、首先server有个用来接收client发送的syn并对syn进行排队的队列,如果队列满了,新的请求不被接受。

此队列长度控制参数:

net.ipv4.tcp_max_syn_backlog 

对应文件(/proc/sys/net/ipv4/tcp_max_syn_backlog ) 默认是1024

1 [root@web]# cat /proc/sys/net/ipv4/tcp_max_syn_backlog
2 1024

二、然后是SYN-ACK重传:当server向client发送syn+ack没有收到相应,server将重传,然后再重传。。。控制这个重传次数的参数是

tcp_synack_retries

对应文件(/proc/sys/net/ipv4/tcp_synack_retries )默认值是5,对应于180秒左右时间

1 [root@web ~]# cat /proc/sys/net/ipv4/tcp_synack_retries
2 5
关于tcp_synack_retries的英文解释:
The maximum number of times a SYN/ACK segment for a passive TCP connection will be retransmitted. This number should not behigher than 255. The default value is 5.
 
备注:与此相对应的client的参数是:
tcp_syn_retries
The maximum number of times initial SYNs for an active TCP connection attempt will be retransmitted. This value should not be higher than 255. The default value is 5, which corresponds to approximately 180 seconds.

三、关于tcp_syncookies

SYN Cookie原理及其在Linux内核中的实现

http://www.ibm.com/developerworks/cn/linux/l-syncookie/?ca=dwcn-newsletter-linux

SYN Cookie是对TCP服务器端的三次握手协议作一些修改,专门用来防范SYN Flood攻击的一种手段。它的原理是,在TCP服务器收到TCP SYN包并返回TCP SYN+ACK包时,不分配一个专门的数据区,而是根据这个SYN包计算出一个cookie值。在收到TCP ACK包时,TCP服务器在根据那个cookie值检查这个TCP ACK包的合法性。如果合法,再分配专门的数据区进行处理未来的TCP连接。

1 [root@web~]# cat /proc/sys/net/ipv4/tcp_syncookies
2 1

===========================================

典型故障处理

如果服务器syn_recv的条数过多,可以采取的操作是:

减少server==>client重传syn+ack的次数。

加大syn队列长度,防止无法响应新的连接

1 echo "net.ipv4.tcp_max_syn_backlog = 4096" >>/etc/sysctl.conf
2 echo "net.ipv4.tcp_synack_retries = 1" >>/etc/sysctl.conf
3 sysctl -p

当受到syn攻击的时候,启用syn-cookie(默认启用,在/etc/sysctl.conf里本身就有参数配置)

1 echo 1 >/proc/sys/net/ipv4/tcp_syncookies

=================================================

四次握手

下面说tcp/ip的第四次握手,分析主动关闭和被动关闭两种。

A:因为如果是CLIENT端主动断掉当前连接,那么双方关闭这个TCP连接共需要四个packet

setup
Client     --->   FIN(M)   --->   Server

client发送一个FIN给server,(说它不跟你玩了),client由ESTABLISHED->FIN_WAIT1

Client    <---  ACK(M+1)  <---   Server 

SER VER收到fin后发送ack确认(拿出两人信物),状态由ESTABLISHED->close_wait


client收到server的ack确认,只是改变状态ESTABLISHED->FIN_WAIT1->FIN_WAIT2,继续等server发送数据。

Client  <--  FIN(N)    <--  Server 

server继续发送FIN到client(好就不玩了吧),状态ESTABLISHED->close_wait->LAST_ACK,等待client发送ack做最后的确认

Client  -->  ACK(N+1)  -->  Server 

client收到FIN,马上发送ack确认,状态ESTABLISHED->FIN_WAIT1->FIN_WAIT2->TIME_WAIT[2MSL超时]->closed

server收到ack确认,状态ESTABLISHED->close_wait->LAST_ACK->CLOSED.

 

client关闭连接很好想,有点要搞清楚的是,server端什么时候会发起丢掉连接的操作:

有些是应用程序控制的。nginx.conf为例

keepalive_timeout  0;
[root@lvs-2 ~]# curl -I http://www.XXX.com
Connection: close


keepalive_timeout  600;
[root@lvs-2 ~]# curl -I http://www.XXX.com
Connection: keep-alive
 

这种规定了连接时间的,到了时间连接会断掉。

如果没有规定的,则按照系统keepalived定时器的设置进行,具体参数如下:

[root@web]# sysctl -a|grep tcp_keepalive

1 net.ipv4.tcp_keepalive_intvl = 75
2 net.ipv4.tcp_keepalive_probes = 9
3 net.ipv4.tcp_keepalive_time = 7200   
4 连接两端一直没发送数据,间隔120分钟,两小时后开始第一次探测,间隔75秒后第二次探测,探测9次,最后放弃连接。有四种探测的情况,详见
5 http://www.360doc.com/content/09/1231/16/96202_12383765.shtml

四种状况其实最后一种没什么意义,能考虑到下面三种就行了

1 client正常,每进行一次通讯,net.ipv4.tcp_keepalive_time重置一次。

2 一直到7200+75*9后也无法获取client反馈信息,则认为client已经关闭并终止连接(连接超时)

3 client重启, 收到探测后返回一个复位(RST)信息。server收到后终止连接(连接被对方复位

 

====================================================================================

典型故障处理

一、网站服务器访问速度变慢,查看网站服务器连接,看到连接至数据库的连接中出现大量time_wait,多达400个。分析是网站服务器定时任务做大量读取数据库操作的时候产生的。
此情况出现在client.

根据上面讲的,time_wait对应2MSL超时,什么是2MSL?,是在client在四次握手的时候最后发送了ack确认给服务器后必然经过的一个时间。TIME_WAIT状态的目的是为了防止最后client发出的ack丢失,让server处于LAST_ACK超时重发FIN。配置2MSL时间长短的服务器参数,但这里不是优化的重要参数,我们需要的是Time_wait的连接可以重用,并且能迅速关闭。

2MSl的解释:

1 [root@bjweba ~]# sysctl -a | grep time | grep wait
2 net.ipv4.netfilter.ip_conntrack_tcp_timeout_time_wait = 120
3 net.ipv4.netfilter.ip_conntrack_tcp_timeout_close_wait = 60
4 net.ipv4.netfilter.ip_conntrack_tcp_timeout_fin_wait = 120

关于 ip_ct_tcp_timeout_time_wait



控制重用和迅速回收的参数是net.ipv4.tcp_tw_reuse和net.ipv4.tcp_tw_recycle。

这两个参数的具体英文解释和作用等我查到了再补充,网上讲的也不怎么清楚。

net.ipv4.tcp_tw_reuse = 1 表示开启重用。允许将TIME-WAIT sockets重新用于新的TCP连接,默认为0

net.ipv4.tcp_tw_recycle = 1 表示开启TCP连接中TIME-WAIT sockets的快速回收,默认为0

1 echo "net.ipv4.tcp_tw_reuse = 1" >>/etc/sysctl.conf
2 echo "net.ipv4.tcp_tw_recycle = 1" >>/etc/sysctl.conf
3 sysctl -p

这样便可以看到time_wait的数量马上降下来了。

二、服务器端运行服务9090的c,或java程序用killall -9 服务名 kill掉后,出现

FIN_WAIT_2状态,新的服务无法启动。因为这个状态占据了服务端口。时间默认1分钟。

1 [root@web ~]# sysctl -a | grep time | grep fin
2 net.ipv4.tcp_fin_timeout = 60

关于FIN_WAIT_2的解释http://httpd.apache.org/docs/1.3/misc/fin_wait_2.html

主要就是服务端主动发起关闭,此时服务端相当于一个client,在最后等对方发送最后一个FIN的却一直等不到,直至超时,控制这个超时的时间参数是tcp_fin_timeout

tcp_fin_timeout(0S)
 
How many seconds to wait for a final FIN packet before the socket is forcibly closed. This is strictly a violation of the TCP specification, but required to prevent denial-of-service (DoS) attacks. The default value in 2.4 kernels is 60, down from 180 in 2.2.
 
备注:TCP_LINGER2(tcp socket编程选项)
The lifetime of orphaned FIN_WAIT2 state sockets. This option can be used to override the system wide sysctl tcp_fin_timeout on this socket. This is not to be confused with the socket (7) level option SO_LINGER. This option should not be used in code intended to be portable.

 

1 echo "net.ipv4.tcp_fin_timeout = 30"  >>/etc/sysctl.conf
2 sysctl -p
3 #echo 30 > /proc/sys/net/ipv4/tcp_fin_timeout

修改方式都有两种,一种是更改/etc/sysctl.conf,还有一种是直接写文件参数文件
http://steven-linux.javaeye.com/blog/540405

 

此外,还有控制tcp发送缓冲区,接收缓冲区大小的设置,能够使用端口范围的设置。

1 [root@web~]# cat /proc/sys/net/ipv4/ip_local_port_range
2 32768   61000

这个是本地连接外地端口时开的动态端口,个人觉得默认就够了。如果有很频繁的要连接外面端口,可以设大。

1 #echo "5000 65535" > /proc/sys/net/ipv4/ip_local_port_range
2 echo "net.ipv4.ip_local_port_range = 5000    65000" >> /etc/sysctl.conf
3 sysctl -p


 


net.ipv4.tcp_keepalive_time = 300
net.ipv4.tcp_syncookies = 1
net.ipv4.tcp_tw_reuse = 1
net.ipv4.tcp_tw_recycle = 1
net.ipv4.ip_local_port_range = 5000    65000

 

参考

http://s135.com
http://linux.chinaunix.net/bbs/thread-901851-1-1.html 
http://lavafree.javaeye.com/blog/700885
http://www.360doc.com/content/10/0613/18/4392_32918827.shtml
http://blog.csdn.net/sky04/archive/2010/07/28/5771797.aspx
http://linux.chinaunix.net/techdoc/net/2008/10/12/1037653.shtml
http://hi.baidu.com/puma_2002/blog/item/c9f04fc5838f7ad6d100609a.html
http://www.sudu.cn/info/html/edu/20080323/275185.html
http://www.oschina.net/bbs/thread/9464
http://blog.csdn.net/hbzhangjian/archive/2008/08/27/2837835.aspx
http://blog.c1gstudio.com/archives/138
http://blog.csdn.net/hbzhangjian/archive/2008/08/27/2837835.aspx
http://blog.163.com/shooow@126/blog/static/461242322007111515720873/
http://syslwx.spaces.live.com/

你可能感兴趣的:(网络,linux)