由dubbo引起的 java OutOfMemoryError unable to create new native thread
先說明結果:
由於linux預設限制1024個執行緒,執行7個tomcat,一個大概150個執行緒左右,外加其中有兩個dubbo佔用了200*2個執行緒,超過1024限制時會出此錯。
解決方法:
1. 修改dubbo配置,降低執行緒數,50-100個足夠。
2. 修改linux配置 /etc/security/limits.conf 把 soft nproc 1024 的1024修改大。
分析工具:jstack,dubbo原始碼
分析,dubbo為什麼要佔用這麼多執行緒:
1. dubbo官方文件標稱,預設使用fixedThreadPool 並且是 100 個。然而我卻發現它的程式碼裡面寫死的是 200 。
2. 其次dubbo使用的是 netty,nio啊,為什麼要用這麼多執行緒。其實netty 只是用來通訊的,nio 工作執行緒數是cpu執行緒數+1個,而上面的 200 是屬於業務執行緒。
3. 下面我會用一段不明朗的語言描述這個過程,之後會有一個簡單的處理過程圖來描述。
語言:
原理是,NettyServer 類建立,建立了cpu執行緒數+1個工作執行緒,即new NioServerSocketChannelFactory()的引數workerCount。這是屬於 netty 的 nio 處理範圍。netty獲取到請求之後,需要處理請求。dubbo 預設情況下使用 dubbo 協議,使用 AllChannelHandler 來處理所有請求,而個類的處理 ChannelEventRunnable extend Runnable 處理,且有域 executor,即通過執行緒池處理,而此執行緒池是使用的 ThreadPool 類擴充套件點,它的註解 @SPI(“fixed”) 決定了它是使用的 FixedThreadPool 型別的執行緒池,這個類裡面的實現是直接使用的 Executors.newFixedThreadPool() 的實現。所以會有200個執行緒。
圖:
綜上所述,dubbo 會佔用較多的執行緒,原因是什麼呢?
netty只用來接收請求,處理很快。後方需要處理業務,可能業務處理會比較慢,所以需要更多的執行緒來完成業務處理。
所以,根據自己的業務量來調整 dubbo 執行緒數量,或者修改linux配置,增加執行緒數。