一、系統需求:
保證後臺系統在大併發下正常處理每一個業務連接請求。
二、運作方式:
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線程給掛死、阻塞。
八、解決方法:
對於複雜的後端業務,分派到專門的業務線程池裏面,進行異步回調處理。