thrift TNonblockingServer 原始碼剖析
關於呼叫流程,有幾點需要著重解釋的: 1. 監聽執行緒只有一個,即#0號IO執行緒。 當新連線被分配給0號執行緒,該連線會進入狀態機轉移註冊相應IO事件,其它IO執行緒會通過pipe通知直接進入狀態轉移; 2. #0號IO執行緒與其它IO執行緒之間、IO執行緒與工作執行緒之間的通訊是基於唯一的連線物件樞紐通過雙向管道,即socketpair系統呼叫建立的unix local domain pipe進行通訊,實現簡潔高效;這種內部執行緒或程序間通訊方式在其它網路庫也很常見。 3. IO事件均依賴libevent庫註冊相關事件事件回撥,這樣使得框架更多關注於如編解碼、任務封裝、具體的業務執行等,IO、work分工協作,增強通用性; 4. 對於連線狀態機不再作具體分析,具體可參考原始碼,比較簡單清晰;像我們自己實現的網路框架也是類似,展示一個連接獲取任務到執行完畢的不同狀態間的transition。 5. 任務(Task)封裝是包含連線(TConnection)在內,而連線的建立包含了工作執行緒的執行體(TProcessor)且建立時機是在監聽到新連線分配IO執行緒時,連線(長)的生命週期遠長於Task,而IO執行緒在資料接收完成後進行Task封裝,工作執行緒僅僅去執行Task對應的TProcessor而不關注其它額外如初始化工作等。 6. 所有工作執行緒是共享一個有工作執行緒池所管理的任務佇列;個人認為這裡可以修改為每個工作執行緒可獨佔一個任務佇列,有主執行緒對task做負載分配(如輪詢),可明顯減少多個工作執行緒爭用同一task佇列的全域性鎖開銷。 7. 對於工作執行緒較重客戶端又急需回覆確認時,需要做相應的任務分解和具體的業務執行優化,或者增加相關緩衝提高業務處理,或者業務上非同步處理,否則會造成QPS下降。