TCP 链接的 TIME_WAIT 过多 致使 Tomcat 假死

最近系统二次开发以后,发现使用的 Tomcat 7 会常常假死。前端点击页面无任何反应,打开firebug,不少连接一直在等待服务器的反应。查看服务器的状态,CPU占用不多,最多不超过10%,通常只有2%,3%左右,内存占用却是接近80, 90%。一开始怀疑是tomcat内存配置不够,可是打开 jvisualvm.exe 分析,发现Tomcat 占用的堆内存没有什么问题。由于是假死,因此最后怀疑到 tomcat的 连接数和 数据库的连接数的配置估计过小了。netstat -na 结果页显示不少time_wait.html

查看各类状态的网络链接的数量:前端

1)Linux 使用命令:netstat -n | awk '/^tcp/ {++S[$NF]} END {for(a in S) print a, S[a]}'nginx

上面的命令能够查出各类状态的网络链接的数量
2)windows使用命令:sql

netstat -n |find /i "time_wait" /c数据库

netstat -n |find /i "close_wait" /capache

netstat -n |find /i "established" /cwindows

windows下没有awk,因此要一个一个状态的统计它们的数量。tomcat

结果是:服务器

1)TIME_WAIT: 状态的链接达到了 709网络

sql server占用的TIME_WAIT最多,还有nginx, tomcat都有一些处于 TIME_WAIT状态。

2)而且最大的端口达到了 65327 ,六万多,几乎接近端口的最大值 65535.

由于是 Windows server 2008,不一样Linux下的TCP的调优。

解决方法:将 TcpTimedWaitDelay 调到 30S,让 TIME_WAIT 状态的维持最多30S,默认是4分钟。

如何查看或设置TcpTimedWaitDelay

cmd中运行 regedit 命令,找到 HKEY_LOCAL_MACHINE/SYSTEM/CurrentControlSet/ Services/TCPIP/Parameters 注册表子键

看看有没有  TcpTimedWaitDelay 项,有的话直接修改,没有的话建立一个并建立名为 TcpTimedWaitDelay 的新 REG_DWORD 值。 将此值设置为十进制 30,其为十六进制 0x0000001e。该值将等待时间设置为 30 秒。 中止并从新启动系统。 缺省值:0xF0,它将等待时间设置为 240 秒(4 分钟)。 建议值:最小值为 0x1E,它将等待时间设置为 30 秒。

修改以后,重启系统,在观察,TIME_WAIT在100左右徘徊。效果仍是立竿见影的。几天来一直再也没有出现Tomcat假死的状况。

 

固然也能够同时 增大 MaxUserPort 的数值(2008最大值好像是 65535):

MaxUserPort :肯定在应用程序从系统请求可用用户端口时,TCP/IP 可指定的最高端口号。默认是65535,能够调到10万.

如何查看或设置: 使用 regedit 命令访问 HKEY_LOCAL_MACHINE/SYSTEM/CurrentControlSet/ Services/TCPIP/Parameters 注册表子键并建立名为 MaxUserPort 的新 REG_DWORD 值,好比设置成200000。

参考:http://www.cnblogs.com/tianzhiliang/articles/2400176.html

 

TIME_WAIT 相关的网络原理,参见:http://www.cnblogs.com/digdeep/p/4869010.html

 

 

 

 

 

 

================================下面的修改没有起做用,可忽略=======================================

修改配置,增长 tomcat 的连接配置:

1.在 conf目录下的 server.xml 中 找到 <Connector 元素加入  maxThreads="800" maxConnections="10000" acceptCount="1000" 

1> maxThreads: 表示最大tomcat能够开启的线程数量,一个线程处理一个请求;

2> maxConneections: 表示最大的socket链接数;

3> acceptCount: 表示当全部的maxThreads的线程都忙于处理时,排队等待被处理的队列的长度;

2. 修改dbcp 数据库(sql server 2005)连接配置:

    <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
        <property name="driverClassName">
            <value>${dataSource_driverClassName}</value>
        </property>
        <property name="url">
            <value>${dataSource_url}</value>
        </property>
        <property name="username">
            <value>${dataSource_username}</value>
        </property>
        <property name="password">
            <value>${dataSource_password}</value>
        </property>
        <!--maxActive: 最大链接数量-->    
        <property name="maxActive" value="150"/>  
        <!--minIdle: 最小空闲链接-->    
        <property name="minIdle" value="5"/>  
        <!--maxIdle: 最大空闲链接-->    
        <property name="maxIdle" value="20"/>  
        <!--initialSize: 初始化链接-->    
        <property name="initialSize" value="30"/>  
        <!-- 链接被泄露时是否打印 -->  
        <property name="logAbandoned" value="true"/>  
        <!--removeAbandoned: 是否自动回收超时链接-->    
        <property name="removeAbandoned"  value="true"/>  
        <!--removeAbandonedTimeout: 超时时间(以秒数为单位)-->    
        <property name="removeAbandonedTimeout" value="10"/> 
        <!--maxWait: 超时等待时间以毫秒为单位 1000等于60秒-->  
        <property name="maxWait" value="1000"/>  
        <!-- 在空闲链接回收器线程运行期间休眠的时间值,以毫秒为单位. -->  
        <property name="timeBetweenEvictionRunsMillis" value="10000"/>  
        <!--  在每次空闲链接回收器线程(若是有)运行时检查的链接数量 -->  
        <property name="numTestsPerEvictionRun" value="10"/>  
        <!-- 1000 * 60 * 30  链接在池中保持空闲而不被空闲链接回收器线程-->  
        <property name="minEvictableIdleTimeMillis" value="10000"/>   
        <property name="validationQuery" value="select 1"/>  
    </bean>

数据库框架采用的是 ibatis 框架。

原来的 dbcp 只有 最上面的四项配置:

        <property name="driverClassName">
            <value>${dataSource_driverClassName}</value>
        </property>
        <property name="url">
            <value>${dataSource_url}</value>
        </property>
        <property name="username">
            <value>${dataSource_username}</value>
        </property>
        <property name="password">
            <value>${dataSource_password}</value>
        </property>

估计就是这里的配置问题。(注:结果该证实猜想是错误的。)

相关文章
相关标签/搜索