由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線程模型簡單代碼說明

綜上所述,dubbo 會佔用較多的線程,原因是什麼呢?
netty只用來接收請求,處理很快。後方需要處理業務,可能業務處理會比較慢,所以需要更多的線程來完成業務處理。

所以,根據自己的業務量來調整 dubbo 線程數量,或者修改linux配置,增加線程數。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章