問(wèn)題描述
- dubbo的線(xiàn)程池內(nèi)所有線(xiàn)程在極短時(shí)間內(nèi)占用完,導(dǎo)致新來(lái)的RPC調(diào)用無(wú)線(xiàn)程可用厉膀,導(dǎo)致出現(xiàn)dubbo自定義的異常信息:RejectedExecutionException查吊,錯(cuò)誤描述為:Thread pool is EXHAUSTED!
問(wèn)題分析
1. dubbo線(xiàn)程池的分析
項(xiàng)目發(fā)布后,發(fā)現(xiàn)生產(chǎn)上面dubbo的線(xiàn)程池迅速被耗盡醋界,查看日志看到如下信息:
Caused by: java.util.concurrent.RejectedExecutionException: Thread pool is EXHAUSTED! Thread Name: DubboServerHandler-10.3.6.32:20890, Pool Size: 200 (active: 200, core: 200, max: 200, largest: 200), Task: 31662 (completed: 31462), Executor status:(isShutdown:false, isTerminated:false, isTerminating:false), in dubbo://10.3.6.32:20890!
RejectedExecutionException是dubbo provide線(xiàn)程池的拒絕策略(詳情見(jiàn):引入dubbo的實(shí)戰(zhàn)記錄),默認(rèn)200大小的線(xiàn)程池被占滿(mǎn)了提完,隨后我們?cè)谶@段日志的上面發(fā)現(xiàn)了另外一段日志:
java.io.IOException: Server returned HTTP response code: 502 for URL: http://backend.ifaclub.com/backend
發(fā)現(xiàn)這個(gè)http請(qǐng)求調(diào)用異常了形纺,并且發(fā)現(xiàn)整個(gè)接口調(diào)用花了100秒,那么問(wèn)題就顯而易見(jiàn)了徒欣,前端一個(gè)請(qǐng)求逐样,發(fā)送到A系統(tǒng),A系統(tǒng)通過(guò)dubbo調(diào)用B系統(tǒng)打肝,B系統(tǒng)http調(diào)用php提供的一個(gè)接口脂新,php的這個(gè)服務(wù)由于一些未知原因特別慢,導(dǎo)致我們的http請(qǐng)求花了很長(zhǎng)時(shí)間粗梭,這時(shí)候dubbo的線(xiàn)程一直得不到釋放争便,由于A系統(tǒng)這時(shí)候頻繁調(diào)用B系統(tǒng),導(dǎo)致B系統(tǒng)的dubbo線(xiàn)程池線(xiàn)程很快被耗盡(dubbo服務(wù)提供方線(xiàn)程池默認(rèn)固定大小200断医,并且SynchronousQueue的初始化大小為0滞乙,也就是說(shuō)線(xiàn)程池總的容量為200)。后來(lái)的解決方案:1.減小http的超時(shí)時(shí)長(zhǎng)(之前設(shè)置的是60秒)鉴嗤;2.加大dubbo線(xiàn)程池容量斩启;這樣就算http調(diào)用會(huì)發(fā)生超時(shí),超時(shí)時(shí)間也很短醉锅,會(huì)讓dubbo線(xiàn)程很快釋放兔簇,增加線(xiàn)程池最大容量就不說(shuō)了。當(dāng)線(xiàn)程池已滿(mǎn)時(shí)硬耍,使用界隊(duì)列來(lái)存儲(chǔ)未執(zhí)行的任務(wù)有這樣一個(gè)好處男韧,當(dāng)發(fā)生異常情況導(dǎo)致線(xiàn)程池被撐滿(mǎn)時(shí),問(wèn)題能盡快的暴露出來(lái)默垄,如果是無(wú)界隊(duì)列,這樣未執(zhí)行的任務(wù)會(huì)一直積壓在隊(duì)列中甚纲,極有可能會(huì)撐滿(mǎn)內(nèi)存口锭,最終導(dǎo)致整個(gè)應(yīng)用不可用。