最近看了下thrift的源碼部分,有小小收獲。以下是對thrift的server層結合自己的理解做一個小小的總結,理解不正確的地方還請大家指出。
(一)簡介
thrift是一個支持多語言之間遠程函數調用的開源工具,因為其方便的使用和對c++、java、php等多種主流語言的支持而獲得廣泛地使用。server層屬於其接受客戶端請求的服務模型層,用於處理接受客戶端過來的請求。
現在支持三種模型:
(1)單線程模型,主線程監聽socket、獲得連接請求、處理請求
(2)多線程模型,主線程監聽socket,獲得新連接,使用threadFactory創建新線程處理該連接直到連接斷開
(3)線程池模型,主線程處理通信請求將獲得的新連接fd生成TConnectedClient加入任務隊列;多個工作線程(ThreadManager管理)從任務隊列取連接、處理請求,直到連接斷開,再從隊列取新的連接
(二)結構
如上圖所示,
TServerFramework是3個服務模型類的基類,通過serve方法提供了處理所有連接請求的循環邏輯,而TSimpleServer、TThreadedServer和TThreadPoolServer三個類分別對應3中服務模型。
TConnectedClient類存儲了連接到服務端的客戶端的相關信息,提供了處理一個請求的方法run,此類繼承於Runnable。
(三)實現
TServerFramework - 提供統一處理循環
mon_ | 限制並發客戶端數量 | Monitor |
clients_ | 並發客戶端數量 | int64_t |
hwm_ | 並發最高值 | int64_t |
limit_ | 並發限制值 | int64_t |
serve方法
循環地從TServerTransport接收clients,通過調用newlyConnectedClient方法送去處理。
newlyConnectedClient調用onClientConnected方法處理連接請求,綁定disposeConnectedClient方法處理連接銷毀,並控制並發連接數。
每個不同的服務模型類提供不同的onClientConnected來實現不同的服務模型。
TSimpleServer - 單線程服務模型
onClientConnected方法
直接調用TConnectedClient的run方法處理請求
TThreadedServer - 多線程服務模型
serve方法
調用TServerFramework的serve,啟動多線程服務模型入口
onClientConnected方法
每到來一個新的連接,都新建一個線程使用TConnectedClient的run進行處理
TThreadPoolServer - 線程池服務模型
threadManager_ | 線程管理 | ThreadManader |
stop_ | voatile bool | |
timeout_ | 等待任務數超限時的超時時間 | volatile int64_t |
taskExpiration_ | 任務過期時間 | volatile int64_t |
serve方法
調用TServerFramework的serve,啟動多線程服務模型入口
threadManager->join等待threadManager的線程池中線程結束
onClientConnected方法
通過使用ThreadManager的add將新的連接請求放入任務隊列
實際處理要等到ThreadManager的Worker線程的run從任務隊列取任務,執行TConnectedClient的run方法。
TConnectedClient - 連接TServer的客戶端
processor_ | 處理類 | TProcessor |
inputProtocol_ | 輸入協議 | TProtocol |
outputProtocol_ | 輸出協議 | TProtocol |
eventHandler_ | TServerEventHandler | |
client_ | 客戶端請求 | TTransport |
opaqueContext_ | 從eventHandler_獲取的上下文 | void* |
run方法
處理一個連接上的請求,直到連接斷開
使用processor的process方法
(四)總結
3種服務模型個有優劣,單線程模型一般只用在調試環境中,同時刻只能處理一個連接;多線程模型同時可以處理多個新連接,但每次處理新的連接都會新建線程,存在不小的開銷;線程池模型一開始就創建好線程,減小了創建線程、銷毀線程開銷,但是多了維護隊列、固定數目線程的開銷。