netty导致tomcat假死

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/aishangyutian12/article/details/52251357

一、系统需求:

保证后台系统在大并发下正常处理每一个业务连接请求。


二、运作方式:

Netty+tomcat。在tomcat的web.xml配置文件中配置一个Listener类用来在tomcat初始化启动时,启动一个Netty服务端,在Netty服务端的Handler中处理每一个连接请求的复杂业务。


三、使用版本:

netty版本:netty-all-5.0.0.Alpha1

jdk版本:Java: 版本 1.7.0_45

tomcat版本:apache-tomcat-8.0.9


四、运作说明:

使用Netty的高并发性能来处理大量的TCP长连接请求,客户端连接到Netty服务端之后,在Handler中调用web应用中相应的类进行处理。


五、出现问题:

收包一段时间(今天测试五个线程同时发,每个线程发送两万左右的数据包,总共大概十万数据包)以后,就会出现tomcat死机状态,日志了不再有任何输出,运行在同一个tomcat上的其他web工程都不能使用了,为什么由tomcat启动的netty协同工作接收大概十万数据包之后出现tomcat假死状态呢?

开源中国提问地址:求问,netty导致tomcat假死


六、问题分析:

6.1,监视线程工具1:jconsole 功能:监控堆内存使用量,线程数,类数量,CPU占用率等. 所在路径:${java安装路径}Java\jdk1.8.0_74\bin

6.2,监视线程工具2:jvisualvm 功能:同jconsole 所在路径:${java安装路径}Java\jdk1.8.0_74\bin 

jvisualvm监控图:


6.3,dump堆内存文件方法:

方法1、在jvisualvm界面监视选项卡的,点击“堆 Dump” 按钮即可生成heapdump文件;

方法2、使用命令jmap -dump:format=b,file=HeapDump.bin <pid>生成(会在界面中显示文件路径),需要查看目标线程的pid(可以查看任务管理器,或者在jconsole或者jvisualvm 工具中查看)。

6.4,dump文件分析工具:MAT(MemoryAnalyzer-1.5.0.20150527-win32.win32.x86_64),打开该软件对6.3中dump出来的dump文件进行分析,可以查看到当前状态下堆内存的使用,以及类的应用情况。

MAT分析结果图:






得到分析结果DefaultEventExecutor占比较高,可能是其出现问题

6.5,对每一个web应用进行监控(找到问题):

1、将javamelody.jar和jrobin-1.5.9.1.jar两个jar包放到web应用的lib中;

2、在web目录下的web.xml文件中加入如下xml片段。

<!-- tomcat监控 -->
<filter>                
       <filter-name>monitoring</filter-name>                
       <filter-class>net.bull.javamelody.MonitoringFilter</filter-class>         
    </filter>        
<filter-mapping>               
<filter-name>monitoring</filter-name>               
<url-pattern>/*</url-pattern>       
</filter-mapping>       
<listener>                
      <listener-class>net.bull.javamelody.SessionListener</listener-class>        
</listener>

3、在浏览器中访问http://localhost:8080/IoT_Harbor/monitoring?period=jour 即可得到当前web应用的监控图,以及所有线程的当前状态。

4、得到正常运行与异常时的线程状态图:

正常状态时:



异常时:



5、对比分析正常运行与异常时所有线程状态发现,后端的NIO线程被阻塞,而执行方法为log4j.


七、找到问题:

测试启动的多个线程,每个线程的测试发包速度为50ms,每次收到数据包Netty的Handler线程中均要对接收数据进行日志打印或者控制台输出,会进行频繁的IO操作,而IO操作会相对耗时。Netty的IO处理线程池,如果遇到非常耗时的业务会很容易把后端的NIO线程给挂死、阻塞。


八、解决方法:

对于复杂的后端业务,分派到专门的业务线程池里面,进行异步回调处理。

猜你喜欢

转载自blog.csdn.net/aishangyutian12/article/details/52251357