1. 程式人生 > 實用技巧 >微服務 - 服務之間的通訊gRPC

微服務 - 服務之間的通訊gRPC

微服務之間的通訊之gRPC

介紹

gRPC是一種與語言無關的高效能遠端過程呼叫 (RPC) 框架,gRPC是Google釋出的基於HTTP 2.0傳輸層協議承載的高效能開源軟體框架,提供了支援多種程式語言的、對網路裝置進行配置和納管的方法。由於是開源框架,通訊的雙方可以進行二次開發,所以客戶端和伺服器端之間的通訊會更加專注於業務層面的內容,減少了對由gRPC框架實現的底層通訊的關注。

gRPC 的主要優點是:

  • 現代高效能輕量級 RPC 框架。
  • 協定優先 API 開發,預設使用協議緩衝區,允許與語言無關的實現。
  • 可用於多種語言的工具,以生成強型別伺服器和客戶端。
  • 支援客戶端、伺服器和雙向流式處理呼叫。
  • 使用 Protobuf 二進位制序列化減少對網路的使用。

這些優點使 gRPC 適用於:

  • 效率至關重要的輕量級微服務。

  • 需要多種語言用於開發的 Polyglot 系統。

  • 需要處理流式處理請求或響應的點對點實時服務。

以上摘自Microsoft Document

微服務中gRPC的互動過程

  1. 交換機在開啟gRPC功能後充當gRPC客戶端的角色,採集伺服器充當gRPC伺服器角色;
  2. 交換機會根據訂閱的事件構建對應資料的格式(GPB/JSON),通過Protocol Buffers進行編寫proto檔案,交換機與伺服器建立gRPC通道,通過gRPC協議向伺服器傳送請求訊息;
  3. 伺服器收到請求訊息後,伺服器會通過Protocol Buffers解譯proto檔案,還原出最先定義好格式的資料結構,進行業務處理;
  4. 資料梳理完後,伺服器需要使用Protocol Buffers重編譯應答資料,通過gRPC協議向交換機發送應答訊息;

交換機收到應答訊息後,結束本次的gRPC互動。上圖展示的是gRPC互動過程的具體流程,這也是Telemetry觸發方式其中之一,稱為Dial-out模式。簡單地說,gRPC就是在客戶端和伺服器端開啟gRPC功能後建立連線,將裝置上配置的訂閱資料推送給伺服器端。我們可以看到整個過程是需要用到Protocol Buffers將所需要處理資料的結構化資料在proto檔案中進行定義。

微服務中gRPC的使用

1、想要使用grpc首先需要先引入gRPC的包

  引入包的方法是:選中服務--->開啟管理庫程式包管理器--->選中瀏覽--->輸入Grpc.AspNetCore --->選中第一個下載即可


  註釋:兩個服務之間需要通訊則這兩個服務都需要引入gRPC的包

2、新增gRPC檔案

  在服務端中新增Protos資料夾(儲存所有gRPC檔案),在資料夾中新增一個 協議緩衝區檔案,檔案字尾為 .proto

  設計 gRPC 的檔案語法,有關 gRPC 檔案語法的詳細資訊,參考一些國內的部落格,如《Protobuf語言指南——.proto檔案語法詳解》。

  我專案中使用的語法:

 1 syntax = "proto3";
 2 
 3 option csharp_namespace = "BS.GrpcServices.WorkTask";
 4 
 5 package BS.GrpcServices.WorkTask;
 6 
 7 service WorkTaskGrpc{
 8     rpc SubmitWorkTask(SubmitRequest) returns (SubmitResponse);
 9 }  
10 
11 message SubmitRequest{
12     string Id = 1;
13     int32  Survey = 2;
14     string OrderId = 3;
15 }
16 
17 message SubmitResponse{
18     bool Result = 1;
19 }

程式碼詳解:

  • BS.GrpcServices.WorkTask:生成的程式集,供外部引用,引入方法:usingBS.GrpcServices.WorkTask;

  • WorkTaskGrpc:程式集中的類,也是儲存服務之間通訊的方法集,引入程式集後通過繼承當前類,則可以呼叫類中的方法

  • SubmitWorkTask:類中的方法,也是兩個服務之間通訊的方法,通訊的主要邏輯均存在當前方法中

  • SubmitRequest:Request預設代表傳入引數,Submit與方法相匹配

  • SubmitResponse:Response預設代表返回值,Submit與方法相匹配

3、專案檔案配置

  雙擊客戶端的服務專案,開啟專案檔案(.csproj字尾的檔案),在檔案中輸入以下程式碼:

<ItemGroup>
  <Protobuf Include="Protos\WorkTask.proto" GrpcServices="Server" />
</ItemGroup>

  輸入完成之後儲存即可;

  雙擊客戶端的服務專案,開啟專案檔案(.csproj字尾的檔案),在檔案中輸入以下程式碼:

<ItemGroup>
  <Protobuf Include="..\BS.WorkTask.API\Protos\WorkTask.proto" GrpcServices="Client" Link="Protos\WorkTask.proto" />
</ItemGroup>

  輸入完成之後儲存即可;

4、Startup.cs檔案

  客戶端開啟Startup.cs檔案,輸入以下程式碼:

AppContext.SetSwitch("System.Net.Http.SocketsHttpHandler.Http2UnencryptedSupport", true); //允許使用不加密的HTTP/2協議
services.AddGrpcClient<WorkTaskGrpc.WorkTaskGrpcClient>(options =>
{
     options.Address = new Uri(Configuration.GetValue<string>("ServiceUrls:WorkTaskAPI"));
});

  程式碼註解:上述程式碼是打通gRPC通訊的最後一個關鍵點,客戶端通過以上方法與gRPC展開通訊,才能訪問到服務端的gRPC程式集(BS.GrpcServices.WorkTask)

  特別注意:上述程式碼的第一行,備註為允許使用不加密的 HTTP/2協議 是一定不能忽略的,少了此行程式碼通訊則無法完成,因為gRPC就是通過當前協議來完成通訊的

5、方法的實現

  實現方法通過引用gRPC程式集,繼承 WorkTaskGrpc.WorkTaskGrpcBase 類,實現方法如下:

 1 using BS.GrpcServices.WorkTask;
 2 using Grpc.Core;
 3 
 4 namespace BS.WorkTask.API.Services
 5 {
 6     public class WorkTaskService : WorkTaskGrpc.WorkTaskGrpcBase
 7     {
 8         public override async Task<SubmitResponse> SubmitWorkTask(SubmitRequest request, ServerCallContext context)
 9         {
10             。。。。。。
11 
12             if(result.Succeeded)
13                 return new SubmitResponse() { Result = true };
14             else
15                 return new SubmitResponse() { Result = false };
16         }
17     }
18 }

  呼叫方法通過引用gRPC程式集,建立WorkTaskGrpc.WorkTaskGrpcClient 物件,通過物件呼叫類中的方法,呼叫方法如下:

 1 using BS.GrpcServices.WorkTask;
 2 
 3 namespace BS.ApiAggregator.Controllers
 4 {
 5     [Route("api/worktask")]
 6     [ApiController]
 7     public class WorkTaskController: ControllerBase
 8     {
 9         WorkTaskGrpc.WorkTaskGrpcClient _workTaskClient;
10         public WorkTaskController(WorkTaskGrpc.WorkTaskGrpcClient workTaskClient)
11         {
12             _workTaskClient = workTaskClient;
13         }
14 
15         [HttpPost("submit")]
16         public async Task<IActionResult> SubmitAsync(GrpcServices.WorkTask.SubmitRequest request)
17         {
18             try
19             {
20                 var clientResult = await _workTaskClient.SubmitWorkTaskAsync(request);
21                 if (clientResult.Result)
22                 {
23                     。。。。。。
24                     return Ok(OperateResult.Success);
25                 }
26             }
27             catch (Exception ex)
28             {
29                 。。。。。
30             }
31         }
32     }
33 }  

  提醒事項:

  1. 中間省略的程式碼是處理邏輯,與gRPC無關
  2. 呼叫方法在客戶端內編寫,實現方法在服務服務端被編寫,兩個位置不可混淆
  3. 客戶端代表的是呼叫方,服務端代表的是被呼叫方

總結:

  gRPC的配置相對來說比較複雜,對於一些服務比較少的微服務來說,不建議使用,可以通過傳統的httpclient通訊即可,相對於純文字傳輸來說,gRPC傳輸的是二進位制資料,使得傳輸資料體積小、負載低,保持更加緊湊和高效,對於傳入的引數較大的情況的話,用gRPC的話則顯得不夠靈活

文章參考自:https://blog.csdn.net/zhaobw831/article/details/101638695

      https://baijiahao.baidu.com/s?id=1633335936037018920&wfr=spider&for=pc