原 netty導致tomcat假死
一、系統需求:
保證後臺系統在大併發下正常處理每一個業務連線請求。
二、運作方式:
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、對比分析正常執行與異常時所有執行緒狀態發現,後端的IO/">NIO執行緒被阻塞,而執行方法為log4j.
七、找到問題:
測試啟動的多個執行緒,每個執行緒的測試發包速度為50ms,每次收到資料包Netty的Handler執行緒中均要對接收資料進行日誌列印或者控制檯輸出,會進行頻繁的IO操作,而IO操作會相對耗時。Netty的IO處理執行緒池,如果遇到非常耗時的業務會很容易把後端的NIO執行緒給掛死、阻塞。
八、解決方法:
對於複雜的後端業務,分派到專門的業務執行緒池裡面,進行非同步回撥處理。