
首先了解一下dubbo線程模型
- 如果事件處理的邏輯能迅速完成,並且不會發起新的IO請求,比如只是在內存中記個標識。則直接在IO線程上處理更快,因為減少了線程池調度。
- 但如果事件處理邏輯較慢,或者需要發起新的IO請求,比如需要查詢數據庫,則必須派發到線程池,否則IO線程阻塞,將導致不能接收其他請求。
- 如果用IO線程處理事件,又在事件處理過程中發起新的IO請求,比如在連接事件中發起登錄請求,會報“可能引發死鎖”異常,但不會真死鎖。
對於Dubbo集群中的Provider角色,有IO線程池(默認無界)和業務處理線程池(默認200)兩個線程池,所以當業務的並發比較高,或者某些業務處理變慢,而且此時我們沒給Provider的線程池配置等待Queue,業務線程池就很容易被“打滿”,拋出“RejectedExecutionException: Thread pool is EXHAUSTED! ”異常。
既然Provider端已經拋出異常,表明自己已經受不了了,但線上我們卻發現,Consumer無動於衷,發出的那筆請求還在一直等待直到超時。這樣極其容易導致整個系統的“雪崩”,因為它違背了fail-fast原則。我們希望一旦Provider由於線程池被打滿而無法收到請求,Consumer應該立即感知然后快速失敗來釋放線程。這是因為Dispatcher配置得不對,默認是all,我們應該配置成message。

所以,為了減少在Provider線程池打滿時整個系統雪崩的風險,將dispatcher設置成message;適當擴大dubbo 接口線程池大小配置 threads;此外,根據系統該接口的低頻調用特點,配置ThreadPool為緩存線程池,避免線程使用完后繼續持有。

