性能测试机中存在大量的TIME_WAIT状态的连接,影响并发压力的发起

来源:互联网 发布:js控制embed 编辑:程序博客网 时间:2024/05/09 10:06

http://www.cnblogs.com/zhuque/archive/2012/11/28/2792539.html



现在一个测试项目,发现性能测试机中有很多TIME_WAIT状态的TCP连接,在网上查了一下,这种状态也叫TCP半连接状态。

测试环境:9台windows测试机,其中包括一台压力控制机,即controller机器

服务器环境:IIS7.0+MS SQL

问题表现:controller机器使用其中任何一台windows测试机并发5个vuser或者更多,都会在8分钟或者10分钟左右出现大量的失败交易

分析:通过在cmd中查看netstat -ano > d:/port.txt(把netstat打印的信息输出到当前D盘根目录下)查看TCP连接,有大量的TIME_WAIT状态的TCP连接,大约有6W多个time_wait状态的TCP连接,咱们windows系统最大端口数量才只有65536个端口,性能测试机每次通过TCP访问server都会占用一个本地端口,导致time_wait状态(半连接状态)过多,并且不释放,导致新的TCP连接去寻找新的端口。如果widows提供的65536个端口全部用完,time_wait状态大量存在,就不会再有新建立的连接,则会出现timeout,导致大量的并发用户数宕掉。这严重影响了并发的发起,该问题已经提交到运维部,请他们来协助

解决办法:

1、修改注册表中的tcpip的属性值:TIMEWAIT回收时间

在HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Tcpip\Parameters,添加名为TcpTimedWaitDelay的DWORD键,设置为十进制0,以缩短TIME_WAIT的等待时间。

测试结果:TIME_WAIT状态的连接依然大量存在,每台机器可以承担少量的并发不会出现错误;当并发增大时则会出现大量的错误。



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


一次压力测试Loadrunner经验分享

http://blog.csdn.net/lxlmj/article/details/6570060


Action.c(4): Error -27796: Failed to connect to server "stadig.ifeng.com:80": [10048] Address already in use

Try changing the registry value 

HKEY_LOCAL_MACHINE/System/CurrentControlSet/Services/tcpip/Parameters/TcpTimedWaitDelay to 30

and HKEY_LOCAL_MACHINE/System/CurrentControlSet/Services/tcpip/Parameters/MaxUserPort to 65534

and rebooting the machine

See the readme.doc file for more information

 

 

压测目标是一个简单的js,服务器处理很快。LR压力测试遇到如上错误,跟据提示在注册表中已将TcpTimedWaitDelay  改为 1;MaxUserPort 改为 65534;并且重启电脑。运行后仍出现上面的错误。后来在 run-time setting/browser emulation中

将simulate a new user on each iteration  选项去掉(默认是选中的)。重新运行一切正常,没有错误出现。

 

猜测原因,客户端性能比较好,发出压力太快,所以把tcp/ip的连接或端口占满。在网上查了一下,xp好像默认开启15个tcp/ip

去掉这个选项的意思是,始终使用一个tcp/ip链接,不断开,也就是开发人员所说的长链接或持久连接。    
短连接:建立连接-----发送和接收报文1-------关闭连接
长连接:建立连接-----发送和接收报文1.。。。2.。。。3-----关闭连接

有大量ESTABLISHED 状态的TCP6连接,并且有若干TIME_WAIT的状态。

端口占用大概在5W6以上。
qatest@db-62:~$ netstat -an|wc -l
56179

而测试机端口数为:
qatest@db-62:~$ cat /proc/sys/net/ipv4/ip_local_port_range
8192 65535

可见,端口基本被用尽。

4. 问题解决

  1. 根据TCP/IP协议,连接断开之后,端口不会立刻被释放,而是处于TIME_WAIT状态,等待60s后(貌似/proc/sys/net/ipv4/tcp_fin_timeout配置),才会被释放掉,才能被新连接使用。
    而性能测试并发了3W连接,每个连接关闭后,grinder又迅速创建新的连接,这时已关闭的连接所占用的端口实际是TIME_WIAT状态,未被释放,不能为新的连接所使用,当所有的端口号均被占用之后,新建连接因为无法分配到端口号而失败。
  2. 修改tpc/ip协议配置,通过配置TCP_TW_REUSE参数,来释放TIME_WAIT状态的端口号给新连接使用
    /proc/sys/net/ipv4/tcp_tw_reuse
    (boolean, default: 0)

    Note: The tcp_tw_reuse setting is particularly useful in environments where numerous short connections are open and left in TIME_WAIT state, such as web servers. Reusing the sockets can be very effective in reducing server load.

  3. 同时修改   /proc/sys/net/ipv4/tcp_tw_recycle
    (boolean, default: 0) 

    TCP_TW_RECYCLE
    It enables fast recycling of TIME_WAIT sockets. The default value is 0 (disabled). The sysctl documentation incorrectly states the default as enabled. It can be changed to 1 (enabled) in many cases. Known to cause some issues with hoststated (load balancing and fail over) if enabled, should be used with caution.

    参考资料:
    http://www.speedguide.net/articles/linux-tweaking-121
  4. 设置参数后,重新测试,不再出现异常情况。
5. 长连接服务器的性能测试中, 修改以上两个参数可以解决问题。但是在并发短连接情况下,还不足以解决问题。比如短连接10ms的情况下,仍然会出现端口号用尽的情况,这个需要修改TIME_WAIT时间,需要进一步调研。


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

TIME_WAIT,CLOSE_WAIT与线程数限制

http://www.cppblog.com/marv/archive/2012/06/27/180495.html

手头的活干得差不多了,代码没多大变动,即便现在使用的单用户单线程模型比较原始也没什么扩展性,单个节点应付不了高并发的访问。在用loadrunner进行压力测试的过程中也发现了些问题,有的是程序问题有的是centos参数设置。
      首先是在服务器端发现了大量套接字处于CLOSE_WAIT状态,套接字使用数不断上升,直到用完了所有的文件描述符不再响应新的请求。根据TCP状态图,知道这种状态是套接字被动关闭,即客户端关闭套接字,服务器再向套接字写入数据则返回broken pipe错误。也就是说,服务器没有正常关闭该套接字,而在回看代码的过程中 又确实调用了closesocket,也尝试过shutdown或者所谓非优雅的关闭套接字设置lingertime选项都没能解决问题。磨了几天,想起来服务线程传入参数不对,传的一个局部变量,过了生存周期,而关闭套接字的时候也自然是返回一个错误。后来改为new一个对象出来作为传入参数在新线程里面delete。
     改过来之后再测,发现周期性的吞吐量下降,用netstat一查发现大量套接字处于TIME_WAIT状态,根据TCP状态图,这个属于正常现象,即等待2MSL时间确保ACK信息以及之前发送的重复包全部消失。如果是在linux系统下可以修改相关参数快速回收TIME_WAIT状态的套接字,修改/etc/sysctl.conf文件,
/sbin/sysctl -p是设置生效
 1 #对于一个新建连接,内核要发送多少个 SYN 连接请求才决定放弃,不应该大于255,默认值是5,对应于180秒左右时间 
 2 net.ipv4.tcp_syn_retries=2
 3 #net.ipv4.tcp_synack_retries=2
 4 #表示当keepalive起用的时候,TCP发送keepalive消息的频度。缺省是2小时,改为300秒
 5 net.ipv4.tcp_keepalive_time=1200
 6 net.ipv4.tcp_orphan_retries=3
 7 #表示如果套接字由本端要求关闭,这个参数决定了它保持在FIN-WAIT-2状态的时间
 8 net.ipv4.tcp_fin_timeout=30 
 9 #表示SYN队列的长度,默认为1024,加大队列长度为8192,可以容纳更多等待连接的网络连接数。
10 net.ipv4.tcp_max_syn_backlog = 4096
11 #表示开启SYN Cookies。当出现SYN等待队列溢出时,启用cookies来处理,可防范少量SYN攻击,默认为0,表示关闭
12 net.ipv4.tcp_syncookies = 1
13 #表示开启重用。允许将TIME-WAIT sockets重新用于新的TCP连接,默认为0,表示关闭
14 net.ipv4.tcp_tw_reuse = 1
15 #表示开启TCP连接中TIME-WAIT sockets的快速回收,默认为0,表示关闭
16 net.ipv4.tcp_tw_recycle = 1
17 ##减少超时前的探测次数
18 net.ipv4.tcp_keepalive_probes=5
19 ##优化网络设备接收队列
20 net.core.netdev_max_backlog=3000
     改好之后,又发现集群里的存储节点在并发量上去的时候容易挂掉,查看日志上面写的pthread failed,resources temporary unavailable,服务器这边也出现这种情况,在网上查了下,linux默认对每个进程的线程数有限制,另一方面默认每个线程8M的栈空间,用户空间的内存有限制,再就是线程资源默认是在主线程调用join 的时候回收。对照代码,线程启动的时候设置了栈为1M,且为DETACHED状态,尝试在ulimit里面修改MAX USER PROCESSER选项,发现没什么效果,最后是修改/etc/security/limits.conf文件,加上2行参数设置可以启动的线程数。
1 * soft nproc 20000  
2 * hard nproc 20000


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

netstat监控大量ESTABLISHED连接与Time_Wait连接问题
http://blog.csdn.net/liuzhenwen/article/details/50245359

在不考虑系统负载、CPU、内存等情况下,netstat监控大量ESTABLISHED连接与Time_Wait连接。

# netstat -n | awk '/^tcp/ {++y[$NF]} END {for(w in y) print w, y[w]}'CLOSE_WAIT         348ESTABLISHED        1240TIME_WAIT          5621

监控Apache与tomcat之间的链接端口

#netstat -n | grep 8009 | wc -l

7198

问题1:怎么解决大量Time_Wait

通过调整内核参数:

复制代码
vim /etc/sysctl.conf#编辑文件,加入以下内容:net.ipv4.tcp_syncookies = 1net.ipv4.tcp_tw_reuse = 1net.ipv4.tcp_tw_recycle = 1net.ipv4.tcp_fin_timeout = 30#然后执行 /sbin/sysctl -p 让参数生效。
复制代码

配置说明:

net.ipv4.tcp_syncookies = 1 表示开启SYN Cookies。当出现SYN等待队列溢出时,启用cookies来处理,可防范少量SYN攻击,默认为0,表示关闭;

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

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

net.ipv4.tcp_fin_timeout=30修改系統默认的 TIMEOUT 时间。

如果以上配置调优后性能还不理想,可继续修改一下配置:

复制代码
vi /etc/sysctl.confnet.ipv4.tcp_keepalive_time = 1200 #表示当keepalive起用的时候,TCP发送keepalive消息的频度。缺省是2小时,改为20分钟。net.ipv4.ip_local_port_range = 1024 65000 #表示用于向外连接的端口范围。缺省情况下很小:32768到61000,改为1024到65000。net.ipv4.tcp_max_syn_backlog = 8192 #表示SYN队列的长度,默认为1024,加大队列长度为8192,可以容纳更多等待连接的网络连接数。net.ipv4.tcp_max_tw_buckets = 5000 #表示系统同时保持TIME_WAIT套接字的最大数量,如果超过这个数字,TIME_WAIT套接字将立刻被清除并打印警告信息。默认为180000,改为5000。对于Apache、Nginx等服务器,上几行的参数可以很好地减少TIME_WAIT套接字数量,但是对于 Squid,效果却不大。此项参数可以控制TIME_WAIT套接字的最大数量,避免Squid服务器被大量的TIME_WAIT套接字拖死。
复制代码

调优完毕,再压一下看看效果吧。

# netstat -n | awk '/^tcp/ {++y[$NF]} END {for(w in y) print w, y[w]}'ESTABLISHED        968

问题1:怎么解决请求结束后依然存在大量ESTABLISHED没有被释放

初步推断tomcat服务器回收session时出了问题,这个一般都跟服务器的Timeout设置有联系。

查看tomcat的配置文件 server.xml

 

<Connector port="8080" protocol="HTTP/1.1"               connectionTimeout="20000"               redirectPort="8443" URIEncoding="UTF-8" />
*****

 

检查配置得出20000毫秒的时候acceptCount=”100” ,明显不合理,最大连接数也太小了吧。

所以进一步优化:

connectionTimeout="20000" 改为 connectionTimeout="100"acceptCount="100"改为acceptCount="5000"

优化完毕,继续压测...

系统响应能力节节攀升,之前LoadRunner报错问题直到压倒***并发也再也没有出现。

Action.c(380): 错误 -26608: 对于“http://www.cnlogs.com/javame”,HTTP 状态代码=504 (Gateway Time-out)




0 0
原创粉丝点击