RPC
整個RPC的定義基本都在hsha_server
這個文件。主要有一下幾個類:
DataFlow
:數據流,所有請求和應答分別保存在兩個線程安全的隊列中。HshaServerStat
HshaServerQos
: 統計運行狀態,獨立線程。Worker
:獨立的工作線程,如果是協程模式,每個worker
會有多個協程。WorkerPool
:工作池,管理Worker
。HshaServerUnit
:獨立線程的工作單元,每個單元都有一個WorkerPool
,UThreadEpollScheduler
和DataFlow
。HshaServerIO
:在HshaServerUnit
線程處理IO事件。HshaServer
:server對象,有多個工作單元。HshaServerAcceptor
:接受連接,工作在主線程。
運行起來有一個accept線程,每個unit有一個IO線程,多個worker線程。
各個模塊之間的關係如下
DataFlow
DataFlow
包含request和response隊列,並附加了時間戳和參數指針。
HshaServerStat HshaServerQos
獨立線程負責統計運行信息,線程綁定爲CallFunc
函數,使用了設置超時時間的條件變量,超時時間爲1s,這樣如果沒有通知則每秒統計一次。
Worker
獨立工作線程,綁定爲Worker::Func
void Worker::Func() {
if (uthread_count_ == 0) { //如果沒有設置協程數量
ThreadMode(); //線程模式
} else {
UThreadMode(); //協程模式
}
}
線程模式直接從DataFlow
中拉一個request然後執行WorkerLogic
。
協程模式創建一個調度器並設置處理新請求的函數。
void Worker::UThreadMode() {
worker_scheduler_ = new UThreadEpollScheduler(utherad_stack_size_, uthread_count_, true);
assert(worker_scheduler_ != nullptr);
worker_scheduler_->SetHandlerNewRequestFunc(bind(&Worker::HandlerNewRequestFunc, this));
worker_scheduler_->RunForever();
}
HandlerNewRequestFunc
會將WorkerLogic
的包裝UThreadFunc
加入調度器的任務隊列。
WorkerLogic
是真正處理邏輯的函數,對沒有超時的請求,會分發到具體的函數處理,最後將結果push到response隊列中。
WorkPool
WorkPool
負責創建Worker
。
HshaServerIO
void HshaServerIO::RunForever() {
scheduler_->SetHandlerAcceptedFdFunc(bind(&HshaServerIO::HandlerAcceptedFd, this));
scheduler_->SetActiveSocketFunc(bind(&HshaServerIO::ActiveSocketFunc, this));
scheduler_->RunForever();
}
RunForever
設置Run
中執行的兩個回調函數分別處理新建連接和寫response
AddAcceptedFd
函數負責將已連接的fd放入accepted_fd_list_
中。
HandlerAcceptedFd
函數從隊列中取出已連接的fd,並綁定IOFunc
函數加入協程調度器的任務隊列。
IOFunc
函數新建一個關聯socketfd的UThreadTcpStream
,然後判斷請求協議的類型並解析請求,將解析完成的request push到DataFlow
中,
然後調用
worker_pool_->Notify();
這一步針對UThreadMode
,worker_pool的Notify
函數會調用worker的Notify
來通知worker的UThreadEpollScheduler
,接下來IOFunc
調用UThreadWait
設置一個超時時間Yield
出去。
此時worker的UThreadEpollScheduler
在Run
函數處輪詢,接下來會執行開啓UThreadMode
時綁定的handler_new_request_func_
也就是Worker::HandlerNewRequestFunc
,這個函數將從DataFlow
中拉取request然後將WorkerLogic
加入worker_scheduler_
的任務隊列。這樣開始執行WorkerLogic
,執行完邏輯後WorkerLogic
將response加入DataFlow
的隊列中。最後執行
pool_->scheduler_->NotifyEpoll();
這一步調用worker_pool_的UThreadEpollScheduler
的NotifyEpoll
,接下來流程回到pool_->scheduler_的Run
中,此時執行active_socket_func_
從DataFlow
中取出response,將其包裝爲該socket的args並返回,最後Resume
到此socket的協程也就是之前的IOFunc
,將response send
出去。
這個應該是整個流程最複雜的一個函數了,主要是worker線程和workpool的UThreadEpollScheduler
的互相喚醒。一次完整的收發數據流程如下:
HshaServerUnit
HshaServerUnit
是IO線程,其RunFunc
AddAcceptedFd
調用的都是成員HshaServerIO
的相應函數。
HshaServerAcceptor
HshaServerAcceptor
的LoopAccept
函數負責accept新連接,idx_
變量通過每次取餘的方式來確定將accept的fd放到哪個HshaServerUnit
。
HshaServer
HshaServer
獲取配置文件中的IO線程數量創建相同數量的HshaServerUnit
,根據配置文件的工作線程數量初始化其參數,然後push到server_unit_list_
中。