您的位置:首页 > 理论基础 > 计算机网络

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

2012-11-14 14:06 1036 查看


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


发布于: November 2, 2010, 4:19 am 分类: Linux 作者: EVE

先贴一个生产环境下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 be
higher
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的解释:

show
source

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

show
source

控制重用和迅速回收的参数是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/

相关日志:

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: