Dubbo執行緒模型與執行緒池策略
- 2019 年 12 月 20 日
- 筆記
一、Dubbo的執行緒模型概述
Dubbo 默認的底層網路通訊使用的是 Netty ,服務提供方 NettyServer 使用兩級執行緒池,其中 EventLoopGroup(boss) 主要用來接受客戶端的鏈接請求,並把接受的請求分發給 EventLoopGroup(worker) 來處理,boss 和 worker 執行緒組我們稱之為 IO 執行緒。
如果服務提供方的邏輯能迅速完成,並且不會發起新的 IO 請求,那麼直接在 IO 執行緒上處理會更快,因為這減少了執行緒池調度與上下文切換開銷。
但如果處理邏輯較慢,或者需要發起新的 IO 請求,比如需要查詢資料庫,則 IO 執行緒必須派發請求到新的執行緒池進行處理,否則 IO 執行緒會被阻塞,將導致不能接收其它請求。
根據請求的消息類被 IO 執行緒處理還是被業務執行緒池處理,Dubbo 提供了下面幾種執行緒模型:
- all:(AllDispatcher 類) 所有消息都派發到業務執行緒池,這些消息包括請求、響應、連接事件,斷開事件,心跳等,這種執行緒模型如下圖7.1.1:

image.png
圖7.1.1
- direct:(DirectDispatcher 類)所有消息都不派發到業務執行緒池,全部在 IO 執行緒上直接執行,模型如下圖圖7.1.2:

image.png
圖7.1.2
- message:(MessageOnlyDispatcher)只有請求響應消息派發到業務執行緒池,其它連接斷開事件、心跳等消息,直接在 IO 執行緒上執行,模型圖如下圖7.1.3:

image.png
圖7.1.3
- execution:(ExecutionDispatcher 類) 只把請求類消息派發到業務執行緒池處理,但是響應和其它連接斷開事件,心跳等消息直接在 IO 執行緒上執行,模型如下圖圖7.1.4:

image.png
圖7.1.4
- connection:(ConnectionOrderedDispatcher類) 在 IO 執行緒上將連接、斷開事件放入隊列,有序逐個執行,其它消息派發到業務執行緒池處理,模型如下圖圖7.1.5:

image.png
圖7.1.5
Dubbo中執行緒模型的擴展介面為Dispatcher,其提供的上述擴展實現都實現了該介面,其中all模型是默認的執行緒模型。
二、Dubbo的執行緒池策略概述
上面我們講解dubbo執行緒模型時候提到為了盡量早的釋放Netty的IO執行緒,某些執行緒模型會把請求投遞到執行緒池進行非同步處理,那麼這裡所謂的執行緒池是什麼樣的執行緒池那?其實這裡的執行緒池ThreadPool也是一個擴展介面SPI,Dubbo提供了該擴展介面的一些實現,具體實現如下:
- FixedThreadPool:創建一個復用固定個數執行緒的執行緒池。
- LimitedThreadPool:創建一個執行緒池,這個執行緒池中執行緒個數隨著需要量動態增加,但是數量不超過配置的閾值的個數,另外空閑執行緒不會被回收,會一直存在。
- EagerThreadPool :創建一個執行緒池,這個執行緒池當所有核心執行緒都處於忙碌狀態時候,創建新的執行緒來執行新任務,而不是把任務放入執行緒池阻塞隊列。
- CachedThreadPool: 創建一個自適應執行緒池,當執行緒處於空閑1分鐘時候,執行緒會被回收,當有新請求到來時候會創建新執行緒
三、總結
Dubbo框架提供了幾種常見的執行緒模型以及實現原理和執行緒池策略,當業務需要訂製執行緒池策略或者執行緒模型時候,可以基於SPI介面進行訂製。本章摘錄自《深度剖析Apache Dubbo核心技術內幕》