![summary-icon](https://cdn-vip.kingdee.com/statics/webfront/summary_icon.png)
本文讨论了客户EAS服务启动失败的问题,原因是TCP连接中大量处于TIME_WAIT状态未释放。TIME_WAIT状态源自TCP四次挥手关闭连接机制,Server端等待2MSL时间确保Client端已断开。高并发下,TIME_WAIT连接积累导致服务器资源耗尽。解决方案是通过修改注册表减少TIME_WAIT等待时间,并重启服务器。
问题概述:
维护项目当中,客户这边发来消息,称自己的EAS服务启动失败,报错如图:
通过cmd输入netstat -an 发现有大量处于TIME_WAIT状态的TCP链接,也就是那些Socket未释放的链接
那么TIME_WAIT状态的来由是什么呢?
TCP链接需要三次握手,四次挥手。可以参考下面流程图:
三次握手建立连接示意图
四次握手关闭连接示意图
从上面的三次握手建立连接示意图中可以知道,只要client端和server端都接收到了对方发送的ACK应答之后,双方就可以建立连接,之后就可以进行数据交互了,这个过程需要三步。
而四次握手关闭连接示意图中,TCP协议中,关闭TCP连接的是Server端(当然,关闭都可以由任意一方发起),当Server端发起关闭连接请求时,向Client端发送一个FIN报文,Client端收到FIN报文时,很可能还有数据需要发送,所以并不会立即关闭SOCKET,所以先回复一个ACK报文,告诉Server端,“你发的FIN报文我收到了”。当Client端的所有报文都发送完毕之后,Client端向Server端发送一个FIN报文,此时Client端进入关闭状态,不在发送数据。
Server端收到FIN报文后,就知道可以关闭连接了,但是网络是不可靠的,Client端并不知道Server端要关闭,所以Server端发送ACK后进入TIME_WAIT状态,如果Client端没有收到ACK则Server段可以重新发送。Client端收到ACK后,就知道可以断开连接了。Server端等待了2MSL(Max Segment Lifetime,最大报文生存时间)后依然没有收到回复,则证明Client端已正常断开,此时,Server端也可以断开连接了。2MSL的TIME_WAIT等待时间就是由此而来。
我们知道了TIME_WAIT的由来,TIME_WAIT 状态最大保持时间是2 * MSL,在1-4分钟之间,所以当系统并发过大,Client-Server连接数过多,Server端会在1-4分钟之内积累大量处于TIME_WAIT状态的无法释放的socket连接,导致服务器效率急剧下降,甚至耗完服务器的所有资源,最终导致No buffer space available (maximum connections reached?): connect问题的发生。
最终解决办法:
通过修改注册表进行配置,减少等待时间。
通过regedit启动注册表编译器找到如下路径:
HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Tcpip\Parameters
添加参数:
(1)新建
值名称:MaxUserPort
值类型:DWORD
值数据:65534(十六进制是FFFE)
有效范围:5000 - 65534 (十进制)
默认:0x1388 5000(十进制)
(2)新建
值名称:TCPTimedWaitDelay
值类型:DWORD
值数据:0000001e(30)
重启windows服务器,是注册表参数生效后,在启动管理控制台,启动服务。
推荐阅读