tomcat close_wait状态过多的处理方法

公司在重新安装应用服务器之后,tomcat+nginx+redis之后,tomcat跑一段时间之后,差不多半个小时之后,就会服务挂掉。这个时候其实自己也不知道原因出在哪里,然后就开始看tomcat的catalina.out的日志,发现有许多内存溢出。其次,使用了netstat -lanput|grep java 发现了该服务器的close_wait状态特别多,当java的子进程达到了server.xml里面的 maxtheards之后,服务就会宕机。

出现CLOSE_WAIT的原因:TCP连接断开时需进行四次挥手,TCP连接的两端都可发起关闭连接的请求,如果对端发起了关闭连接,但本地没进行后续的关闭连接操作,那么该链接就会处于CLOSE_WAIT状态。虽然该链接已经处于半开状态,但已不能和对端通信,需及时的释放该链接。

于是我开始了在tomcat里面进行调试,

<Executor name="tomcatThreadPool" namePrefix="catalina-exec-"

maxThreads="1000" minSpareThreads="20" maxIdleTime="10000"/>

 

这个是开启tomcat线程池的,在tomcat里面默认注释了server.xml里面, maxThreads的意思是能开启的线程最大数量(超过1000的之后的请求只能排队,等待有线程释放后,才能被处理),minSpareThreads是默认最小保持线程的数量,maxIdleTime=600000是默认值,代表当目前线程数量 大于 最小保持minsparethreads之后,便会启动这个机制,60秒就清除不活跃的线程。

但是这个默认值对我来说还是太大了,于是将60秒改为了10秒。connector配置如下

 

<Connector port="8080" protocol="org.apache.coyote.http11.Http11NioProtocol"

executor="tomcatThreadPool" #开启线程池

connectionTimeout="30000"

connectionUploadTimeout="120000"

disableUploadTimeout="true" #上传文件的连接时间,可以调大一些

acceptCount="800"

maxKeepAliveRequests="1"

enableLookups="false"

bufferSize="512"

socketBuffer="512"

redirectPort="8443" URIEncoding="utf-8"/>

 

connectionTimeout #连接超时时间建立一个socket连接后,如果一直没有收到客户端的FIN,也没有数据过来,那么此连接也必须等到30s后,才能被超时释放

acceptCount 当tomcat起动的线程数达到最大时,接受排队的请求个数,默认值为100

maxThreads 不能过大,如果太大的话cpu会消耗大量资源在切换线程,会导致服务器比较卡

 

从系统内核方面进行优化keepalive vim /etc/sysctl.cnf

net.ipv4.ip_forward = 1 #开启路由转发

net.ipv4.ip_nonlocal_bind = 1 #允许绑定非本机ip

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

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

net.ipv4.tcp_tw_recycle = 1 #表示开启TCP连接中TIME-WAIT sockets的快速回收

net.ipv4.tcp_fin_timeout = 30 #表示如果套接字由本端要求关闭,这个参数决定了它保持在FIN-WAIT-2状态的时间

上面的4条是优化 time_wait过多的情况

 

net.ipv4.tcp_keepalive_time = 30

net.ipv4.tcp_keepalive_probes = 3

net.ipv4.tcp_keepalive_intvl = 15

 

使用 watch -n1 -d 'netstat -lanput |grep java |wc -l'检测tomcat的状态

 

使用脚本对tomcat进行控制,每2分钟启用一次判断tomcat的状态

 

#!/bin/bash

tompid=`ps -ef |grep tomcat |grep '/usr/local/'|awk '{print $2}'`

#判断tomcat的pid

pingcu()

{

curl --connect-time 5 -m 10 -s tomcat应用的网址

}

#使用curl测试网页是否畅通,如果线程堆积,curl无法正常访问tomcat

pingcu >/dev/null

result=$?

#能正常访问的话echo $?的值是0 不能的话是非0值

if [ $result -ne 0 ]; then

echo `date "+%Y-%m-%d %H:%M:%S"`>> /usr/local/risingtech/tom.log

echo -e "\e[31m\e[1mtomcat is died\e[0m" >> /usr/local/risingtech/tom.log

#加上一个时间戳 判断tomcat的启动频率

kill -9 $tompid

echo "成功杀死" >> /usr/local/risingtech/tom.log

/usr/local/tomcat/bin/catalina.sh start && echo -e "\e[32m\e[1mtomcat 重启完毕\e[0m" >>/usr/local/risingtech/tom.log

exit 2

else

echo `date "+%Y-%m-%d %H:%M:%S"`>> /usr/local/risingtech/tom.log

echo -e "\e[32m\e[1mtomcat is alived\e[0m" >> /usr/local/risingtech/tom.log

fi

 

最好定时任务时间错开,避免2个同时重启,导致无法正常访问

最好还是通过代码上的修改解决问题

 

最终问题已经解决了。

在修改之后过了一段时间,访问过大的情况还是会出现close_wait特别多的情况,今天在测试的时候发现,查看nginx的访问log,提取了一个文件

cat /usr/local/nginx/logs/access.log |grep 项目地址(提取接口) |awk '{print $4,$7}' > jiekou.txt

cat jiekou1.txt |sort |uniq -c >jieguo.txt

#去从接口访问,排序那个接口访问的量最大

得到了一个特别多的amq访问,这个是在网页上的聊天功能,经过控制变量发现,这个东西开启了之后就会每次刷新一次首页,就会出现2个CLOSE_WAIT状态,

vim /usr/local/tomcat/webapps/cu/WEB-INF/web.xml

 

<!-- activeMQ -->

<!-- <servlet>

<servlet-name>AjaxServlet</servlet-name>

<servlet-class>org.apache.activemq.web.AjaxServlet</servlet-class>

<load-on-startup>1</load-on-startup>

<async-supported>true</async-supported>

</servlet>

<servlet-mapping>

<servlet-name>AjaxServlet</servlet-name>

<url-pattern>/amq/*</url-pattern>

</servlet-mapping>

-->

注释了之后发现,close_wait没有上涨了,开发说是因为当时没有做超时限制,最终还是解决了这个问题

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值