RPC的概念
RPC 全稱 Remote Procedure Call——遠端過程呼叫。是為了解決遠端呼叫服務的一種技術,使得呼叫者像呼叫本地服務一樣方便透明。簡單的說,RPC就是從一臺機器(客戶端)上通過引數傳遞的方式呼叫另一臺機器(伺服器)上的一個函式或方法(可以統稱為服務)並得到返回的結果。
RPC框架的目標就是讓遠端過程(服務)呼叫更加簡單、透明,RPC框架負責遮蔽底層的傳輸方式(TCP或UDP)、序列化方式(XML/JSON/二進位制)和通訊細節。框架使用者只需要瞭解誰在設麼位置提供了什麼樣的遠端服務介面即可,開發者不需要關心底層通訊細節和呼叫過程。
RPC通訊有如下特點:
- RPC 會隱藏底層的通訊細節(不需要直接處理Socket通訊或Http通訊)
- RPC 是一個請求響應模型。客戶端發起請求,伺服器返回響應(類似於Http的工作方式)
- RPC 在使用形式上像呼叫本地函式(或方法)一樣去呼叫遠端的函式(或方法)。
一個RPC框架由三部分組成:
-
服務提供者: 它執行在服務端,負責提供服務介面定義和服務實現類。
-
服務釋出者:它執行在RPC服務端,複雜將本地服務釋出成遠端服務,供其他消費者呼叫。
-
本地服務代理: 它執行在RPC客服端,通過代理呼叫遠端服務提供者,然後將結果進行封裝給本地消費者。
RPC通訊模型如下圖所示:
Lms的rpc框架實現
LMS框架使用rpc協議實現服務之間的通訊。我們知道,要實現一個RPC框架,需要解決幾個如下技術點:
-
遠端服務提供者:需要以某種形式提供服務呼叫相關的資訊,包括但不限於服務連線口定義、資料介面、或者中間態的服務定義檔案;在LMS框架中,服務提供者以服務應用介面的方式提供服務呼叫的相關資訊,服務呼叫者通過引用服務提供者的應用服務介面層(專案、包)的方式獲取遠端服務呼叫的相關資訊。
-
遠端代理物件:服務呼叫者呼叫的服務實際上是遠端服務的本地代理,對於LMS框架而言,通過
Castle.Core
元件的動態代理攔截機制,將本地呼叫封裝成遠端服務呼叫。 -
通訊:RPC框架於具體的通訊協議無關;LMS框架使用dotnetty框架作為底層的通訊框架。
-
序列化:遠端通訊,需要將物件轉換成二進位制碼流進行網路傳輸,不同的序列化框架,支援的資料型別/資料包大小、異常型別以及效能等都不同。LMS框架預設使用json格式作為序列化格式,也支援通過
MessagePack
或是Protobuff
作為序列化方式。
如何使用
在LMS框架中,服務呼叫者(消費者)通過引用服務提供者的應用介面層(包),就可以通過Castle.Core
元件的動態代理攔截機制為服務應用介面生成本地代理,通過該代理與應用服務提供者進行通訊,並將返回的介面封裝給消費者,步驟如下所述:
-
將服務提供者的應用介面單獨定義為一個應用程式集(包)。定義的應用介面需要通過
ServiceRouteAttribute
對服務應用介面的路由進行標識,服務提供者需要實現應用介面。 -
服務呼叫者服務需要通過專案(或是通過nuget包安裝)的方式引用服務提供者的應用介面所定義的專案(包)。
-
開發者可以通過構造注入的方式使用應用服務介面,服務呼叫者就可以通過服務呼叫者的應用介面生成的動態代理與服務提供者進行通訊。
public class TestProxyAppService : ITestProxyAppService
{
private readonly ITestAppService _testAppServiceProxy; // 應用提供者的應用介面,通過其生成服務呼叫者的本地動態代理
private readonly ICurrentServiceKey _currentServiceKey;
public TestProxyAppService(ITestAppService testAppService,
ICurrentServiceKey currentServiceKey)
{
_testAppServiceProxy = testAppService;
_currentServiceKey = currentServiceKey;
}
public async Task<TestOut> CreateProxy(TestInput testInput)
{
// _currentServiceKey.Change("v2");
// 通過應用介面生成的本地動態代理與服務提供者進行rpc通訊
return await _testAppServiceProxy.Create(testInput);
}
}
備註
在rpc通訊過程中,通過指定的ServiceKey
來指定服務提供者的應用介面的實現類,可以在服務呼叫前,通過currentServiceKey.Change("serviceKeyName")
來指定該rpc通訊的serviceKey
的值。
開源地址與文件
github: https://github.com/liuhll/lms
gitee: https://gitee.com/liuhll2/lms
開發者文件: http://docs.lms-fk.com/
加入我們
qq群: 934306776