我是誰?(Local Actor)
如何告訴别人我是誰?(Actor Directory)
我提供什麼服務?(Service Catalog Provider)
如何告訴别人我提供什麼服務?(Service Directory)
我需要的服務在哪裡?(Service Discovery)
如何調用該服務?(Service Dynamic Proxy)
如何找到該服務?(Actor Directory)
如何發消息給該服務?(Remote Actor)
Redola 定義的 Actor 模型代表着一個通信節點,使用 ActorIdentity 描述,包括節點類型 Type、節點名稱 Name、節點位址 Address、節點端口 Port。
Actor 與 Actor 之間是基于 TCP Socket 通信的,Actor 并不區分 TCP 的 Server/Client 端,它将 Server 和 Client 封裝在底層,為上層應用提供更便捷的傳輸定義和調用接口。Actor 模型提供了面向通道 Channel 的雙工通道,可以接收來自對端的消息,也可以發送消息給對端。
Actor 收發的消息是面向二進制數組的,它不關心具體發送的是什麼消息,也不關心序列化格式。Actor 使用 ActorFrameHeader 定義傳輸消息頭,Header 攜帶消息體長度。
Actor 一旦建立連接配接,生成的 Channel 通道會自動進行 KeepAlive 雙向保活機制。通過 Actor 服務發現,可以與任意的 Actor 進行通信,無需再配置對端節點位址和端口。并且,針對相同 Type 的 Actor,還可以實作消息分發的負載均衡功能。
例如,下面是定義 ICalcService 服務的 IDL 定義。
<a></a>
上述 IDL 生成的 ICalcService 接口定義為:
使用 ActorMessageEnvelope 封裝消息信封,攜帶如下資訊:
屬性名稱
屬性類型
屬性描述
MessageID
string
消息 ID,唯一 ID,通常使用 GUID。
MessageTime
DateTime
消息産生時間
CorrelationID
如果是 Response 則回填 Request 的 MessageID。
CorrelationTime
DateTime
如果是 Response 則回填 Request 的 MessageTime。
SourceEndpoint
ActorEndpoint
發送端節點描述,消息路由使用,預設不需要填寫。
TargetEndpoint
ActorEndpoint
目的端節點描述,消息路由使用,預設不需要填寫。
MessageType
消息類型,使用字元串描述。
MessageData
byte[]
消息體,消息序列化後的二進制數組。
RPC 消息分為 2 類:
InvokeMethodRequest / InvokeMethodResponse 用于定義請求回複模型的方法調用;
InvokeMethodMessage 用于定義請求無回複模型的方法調用;
通常 RPC 消息會包含如下屬性資訊:
MethodLocator
RPC 方法描述,使用字元串描述。
MethodArguments
object[]
RPC 方法的入參,object 對象數組。
例如,對于 ICalcService 中的 Add 方法:
MethodLocator = "Rodola.Rpc.TestContracts.ICalcService/Add_AddRequest";
MethodArguments = new object[] { new AddRequest(1, 2)};
Actor Directory 負責注冊本地 Local Actor 到注冊中心,Local Actor 也可以在 Shutdown 時将自己從注冊中心移除掉。
通過 Actor Directory,Local Actor 可以使用 Type 和 Name 進行 Remote Actor 的檢索,進而進行 Channel 的建立和通信。
Actor Directory 通過 IActorDirectory 的抽象定義,可以與不同的目錄方案進行內建。例如,自實作基于 Actor 的 CenterActorDirectory,使用 XML 配置檔案的 LocalXmlFileActorDirectory,使用 Consul 進行中心注冊的 ConsulActorDirectory。
通過如下 cmd 啟動 Consul Server 和 Consul Agent。
下面為啟動本地 Consul 進行測試的配置檔案。
server-01.json
client-01.json
作為 RPC Service 的 Provider 提供方,需要顯式定義指定 Contract 的服務執行個體。例如,下面将不同的服務契約與服務執行個體進行了注冊。
實際上,可以通過對于 IServiceCatalogProvider 接口的不同實作,進行不同方式的本地服務發現和注冊。例如,可以使用 Attribute 标記服務,通過對 Assembly 進行反射進行服務的執行個體化。
本地服務聚集到 Catalog 中後,系統會将服務逐個注冊到 Service Directory 服務目錄中,使得其他節點可以檢索服務進行使用。
通過 IServiceDirectory 的抽象定義,可以與不同的目錄方案進行內建。例如,使用 XML 配置檔案的 LocalXmlFileServiceDirectory,使用 Consul 進行中心注冊的 ConsulServiceDirectory。
使用 Consul 時,注冊服務的 log 如下所示。

當 Redola 将服務注冊至 Consul 中後,可通過 Consul 内置的 UI 進行檢視。
通過 Postman 測試 GET /v1/catalog/services,得到如下 JSON 資料。
通過 Postman 測試 GET /v1/catalog/service,得到如下 JSON 資料。
服務檢索方,可通過指定 IServiceLoadBalancingStrategy 的具體實作實施不同的負載均衡政策,預設指定的是 IServiceLoadBalancingStrategy 随機選擇。
為簡化 RPC 調用發起方的封裝,通常會使用 Dynamic Proxy 動态代理技術來動态生成給定契約的服務執行個體,将整體 RPC 的過程透明化。
例如,通過下面的代碼來動态生成 ICalcService 的動态代理。
當然,如需內建其他 Dynamic Proxy 類庫,可通過 ISeviceProxyGenerator 接口進行方案實作。
Redola.Rpc 目前實作依賴了如下開源類庫。
<a>本文轉自匠心十年部落格園部落格,原文連結:http://www.cnblogs.com/gaochundong/p/redola_rpc_consul_integration.html,如需轉載請自行聯系原作者</a>