1. 程式人生 > >ASP.NET Core 3.0 使用gRPC

ASP.NET Core 3.0 使用gRPC

一.簡介

gRPC 是一個由Google開源的,跨語言的,高效能的遠端過程呼叫(RPC)框架。 gRPC使客戶端和服務端應用程式可以透明地進行通訊,並簡化了連線系統的構建。它使用HTTP/2作為通訊協議,使用 Protocol Buffers 作為序列化協議。

它的主要優點:

  • 現代高效能輕量級 RPC 框架。
  • 約定優先的 API 開發,預設使用 Protocol Buffers 作為描述語言,允許與語言無關的實現。

  • 可用於多種語言的工具,以生成強型別的伺服器和客戶端。
  • 支援客戶端,伺服器雙向流呼叫。
  • 通過Protocol Buffers二進位制序列化減少網路使用。
  • 使用 HTTP/2 進行傳輸

這些優點使gRPC非常適合:

  • 高效能輕量級微服務。
  • 需要多種程式語言同時使用的專案。
  • 需要處理流式請求或響應的點對點實時服務。

摘自微軟官方文件

支援的語言如下:

二.gRPC on .NET Core

gRPC 現在可以非常簡單的在 .NET Core 和 ASP.NET Core 中使用,在 .NET Core 上的實現的開源地址:https://github.com/grpc/grpc-dotnet ,它目前由微軟官方 ASP.NET 專案的人員進行維護,良好的接入 .NET Core 生態。

.NET Core 的 gRPC 功能如下:

  • Grpc.AspNetCore 一個用於在ASP.NET Core承載gRPC服務的框架,將 gRPC和ASP.NET Core 功能整合在一起,如:日誌、依賴注入、身份認證和授權。
  • Grpc.Net.Client 基於HttpClient (HttpClient現已支援HTTP/2)的 gRPC客戶端
  • Grpc.Net.ClientFactory 與gRPC客戶端整合的HttpClientFactory,允許對gRPC客戶端進行集中配置,並使用DI注入到應用程式中

三.使用 ASP.NET Core 建立 gRPC 服務

  1. 通過 Visual Studio 2019 (16.3.0)提供的模板,可以快速建立 gRPC 服務。

來扒拉一下預設原始碼包含了什麼東東。

① 配置檔案 appsettings.json ,多了Kestrel 啟用 HTTP/2 的配置,因為 gRPC 是基於 HTTP/2 來通訊的

② PB協議檔案 greet.proto 用於自動生成服務、客戶端和訊息(表示傳遞的資料)的C# Class

③ 服務類 GreeterService ,服務類整合的 Greeter.GreeterBase 來自於根據proto檔案自動生成的,生成的類在 obj\Debug\netcoreapp3.0目錄下

自動生成的類:

Startup.cs類,將 gRPC服務新增到了終結點路由中

⑤ csproj 專案檔案,包含了 proto 檔案引用

2.執行

第一次執行會提示是否信任證書,點選“是”

這是因為HTTP/2需要HTTPS,儘管HTTP/2協議沒有明確規定需要HTTPS,但是為了安全在瀏覽器實現上都要求了HTTPS,所以現在的HTTP/2和HTTPS基本都是一對。

四. 建立 gRPC 客戶端

1.新增一個.NET Core 控制檯應用程式

2.通過nuget新增包:Grpc.Net.Client、Google.Protobuf、Grpc.Tools

3.將服務的 proto 檔案複製到客戶端

4.編輯客戶端專案檔案,新增關於proto檔案的描述

<ItemGroup>
    <Protobuf Include="Protos\greet.proto" GrpcServices="Client" />
</ItemGroup>

注意 GrpcServices="Client" 這裡是Client和服務是不一樣的

5.生成客戶端專案可以通過proto檔案生成類

6.新增客戶端呼叫程式碼

static async Task Main(string[] args)
{
    var channel = GrpcChannel.ForAddress("https://localhost:5001");
    var client = new Greeter.GreeterClient(channel);
    var reply = await client.SayHelloAsync(
        new HelloRequest { Name = "曉晨" });
    Console.WriteLine("Greeter 服務返回資料: " + reply.Message);
    Console.ReadKey();
}

7.先啟動服務,然後執行客戶端

這裡可以看到,客戶端成功呼叫了服務,收到了返回的訊息。

五.自己動手寫一個服務

前面我們使用的 Greeter 服務是由模板自動給我們建立的,現在我們來自己動手寫一個服務。

編寫一個“擼貓服務”

1.定義 proto 檔案 LuCat.proto,並在csproj專案檔案中新增描述

syntax = "proto3";

option csharp_namespace = "AspNetCoregRpcService";

import "google/protobuf/empty.proto";
package LuCat; //定義包名

//定義服務
service LuCat{
    //定義吸貓方法
    rpc SuckingCat(google.protobuf.Empty) returns(SuckingCatResult);
}

message SuckingCatResult{
    string message=1;
}

2.實現服務 LuCatService.cs

public class LuCatService:LuCat.LuCatBase
{
    private static readonly List<string> Cats=new List<string>(){"英短銀漸層","英短金漸層","美短","藍貓","狸花貓","橘貓"};
    private static readonly Random Rand=new Random(DateTime.Now.Millisecond);
    public override Task<SuckingCatResult> SuckingCat(Empty request, ServerCallContext context)
    {
        return Task.FromResult(new SuckingCatResult()
        {
            Message = $"您吸了一隻{Cats[Rand.Next(0, Cats.Count)]}"
        });
    }
}

3.在 Startup終結點路由中註冊

endpoints.MapGrpcService<LuCatService>();

4.新增客戶端呼叫

var catClient = new LuCat.LuCatClient(channel);
var catReply = await catClient.SuckingCatAsync(new Empty());
Console.WriteLine("呼叫擼貓服務:"+ catReply.Message);

5.執行測試

六.實際使用中的技巧

技巧1

上面章節的操作步驟中,我們需要在服務和客戶端之間複製proto,這是一個可以省略掉的步驟。

1.複製 Protos 資料夾到解決方案根目錄(sln檔案所在目錄)

2.刪除客戶端和服務專案中的 Protos 資料夾

3.在客戶端專案檔案csproj中新增關於proto檔案的描述

  <ItemGroup>
    <Protobuf Include="..\..\Protos\greet.proto" GrpcServices="Client" Link="Protos\greet.proto" />
  </ItemGroup>

4.在服務專案檔案csproj中新增關於proto檔案的描述

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

在實際專案中,請自己計算相對路徑

5.這樣兩個專案都是使用的一個proto檔案,只用維護這一個檔案即可

技巧2

我們在實際專案中使用,肯定有多個 proto 檔案,難道我們每新增一個 proto 檔案都要去更新 csproj檔案?

我們可以使用MSBuild變數來幫我們完成,我們將 csproj 專案檔案中引入proto檔案資訊進行修改。

服務端:

  <ItemGroup>
    <Protobuf Include="..\..\Protos\*.proto" GrpcServices="Server" Link="Protos\%(RecursiveDir)%(Filename)%(Extension)" />
  </ItemGroup>

客戶端:

  <ItemGroup>
    <Protobuf Include="..\..\Protos\*.proto" GrpcServices="Client" Link="Protos\%(RecursiveDir)%(Filename)%(Extension)" />
  </ItemGroup>

示例:

七.總結

gRPC 現目前是一款非常成熟的高效能RPC框架,當前的生態是非常好的,很多公司的產品或者開源專案都有在使用gRPC,有了它,相信可以讓我們更容易的構建.NET Core 微服務,可以讓 .NET Core 更好的接入 gRPC 生態。不得不說這是 .NET Core 3.0 帶來的最令人振奮的特性之一。

參考資料:

  • proto3 說明文件
  • 在ASP.NET Core中建立gRPC客戶端和服務
  • Demo 地址

如果大家無法訪問proto3說明文件,這裡提供一個離線網頁版(請另存為下載後用Chrome開啟)