ET框架的訊息機制貫徹始終,包含Entity訊息(Awake,Update ...),自定義(Customer)訊息,網路訊息等。而ET系統的程序包含了使用者端、Gate等各種型別的伺服器,程序包含各種伺服器使用者端之間通過網路訊息進行通訊進行工作。
結構圖為了更加明確整體關係,進行了一定程度的簡化,剔除掉了一些訊息解包等一些細節
NetCompontent網路元件有Client使用者端、Server伺服器(Gate)、Inner內網服務等多型,程序業務使用網路元件進行通訊,網路元件會對連線建立一個Secsiom對談物件,封裝連線資訊和相關操作
Service和Channel實現負責NetCompontent和Session的功能,有Tcp長連線、Web網頁、KCP無連線可靠協定的多型(若不熟悉KCP協定,可以參考之前寫的文章 跳轉連結: KCP協定淺析)。
NetServices負責排程多個Service物件的在網路執行緒和主執行緒工作任務,ET開了網路執行緒處理網路相關,某些程序需要多個網路元件(比如Gate伺服器同時需要Server、Inner網路元件,接收轉發使用者端訊息)。
NetComponentOnReadEvent是不同型別網路元件的訊息處理器。
以典型的TCP協定型別為例,其他實現類似,看圖相信都能理解,不多贅述。有一些要注意的點:
ET框架在基礎網路訊息通訊基礎使用了Actor模型、PRC等相關技術思想(某些思想和實現有調整)進行了拓展,提供多個程序的互相呼叫機制。
先對相關技術做一個簡介:
在電腦科學中,Actor模型(Actor model)是一種並行運算上的模型。「Actor」是一種程式上的抽象概念,被視為並行運算的基本單元:當一個Actor接收到一則訊息,它可以做出一些決策、建立更多的Actor、傳送更多的訊息、決定要如何回答接下來的訊息。Actor可以修改它們自己的私有狀態,但是隻能通過訊息間接的相互影響(避免了基於鎖的同步)
這是維基百科中對於Actor模型的描述,簡單理解它就是提供了一種訊息機制避免了基於鎖的同步。一些經典的應用場景是多執行緒,在ET框架中它的應用場景是多程序,類似的它提供了一種機制:直接通過ID發訊息,不用關心範例在哪個程序。
分散式計算中,遠端過程呼叫(英語:Remote Procedure Call,RPC)是一個計算機通訊協定。該協定允許執行於一臺計算機的程式呼叫另一個地址空間(通常為一個開放網路的一臺計算機)的子程式,而程式設計師就像呼叫本地程式一樣,無需額外地為這個互動作用程式設計(無需關注細節)。RPC是一種伺服器-使用者端(Client/Server)模式,經典實現是一個通過傳送請求-接受迴應進行資訊互動的系統
RPC機制通過一些手段抹平了不同程序的差異,使得程序間的呼叫可以和本地非同步呼叫一樣處理。
瞭解了這兩種技術,下面來看ET框架對其的應用和如何實現多程序呼叫的。
如上圖所示訊息型別分為三種:
注意Request和Response一定成對定義,且其Message一定包含一個RpcId欄位
訊息型別可以被字首修飾,修飾有三種:
修飾字元可以修飾任意訊息型別,組合起來一共有9種訊息。
如這個登入到Gate的協定:
//ResponseType G2C_LoginGate
message C2G_LoginGate // IRequest
{
int32 RpcId = 1;
int64 Key = 2; // 帳號
int64 GateId = 3;
}
message G2C_LoginGate // IResponse
{
int32 RpcId = 1;
int32 Error = 2;
string Message = 3;
int64 PlayerId = 4;
}
如圖所示,進行Rpc呼叫時,生成一個新的RpcID並帶入請求包中,同時把呼叫資訊存起來。對方應答時,會把請求包的RpcID傳入到應答包中。在收到訊息時如果是Resp型別訊息會呼叫OnResp方法,通過應答包的RpcID取出RpcInfo,通過RpcInfo取消呼叫RpcCall函數的非同步阻塞。
public static void OnResponse(this Session self, IResponse response)
{
if (!self.requestCallbacks.TryGetValue(response.RpcId, out var action))
{
return;
}
self.requestCallbacks.Remove(response.RpcId);
if (ErrorCore.IsRpcNeedThrowException(response.Error))
{
action.Tcs.SetException(new Exception($"Rpc error, request: {action.Request} response: {response}"));
return;
}
action.Tcs.SetResult(response);
}
action.Tcs.SetResult會取消非同步的阻塞,執行await後面的語句,詳情見之前寫的文章 跳轉連結: C#非同步程式設計
在ET框架的設計中,Actor其實是一個帶有MailboxComponent的元件。其具體的實現方式,ET有比較詳細的檔案說明,有實現思路和使用方式的介紹,這裡貼出來,不做贅述。
跳轉連結: ET Actor模型 官方介紹