gRPC在 ASP.NET Core 中應用學習

chaney1992發表於2021-03-07

一、gRPC簡介:

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

 引用自微軟文件:

gRPC 的主要優點是:

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

這些優點使 gRPC 適用於:

  • 效率至關重要的輕量級微服務。
  • 需要多種語言用於開發的 Polyglot 系統。
  • 需要處理流式處理請求或響應的點對點實時服務。

 官方支援的gRPC語言,平臺和作業系統版本

LanguageOSCompilers / SDK
C/C++ Linux, Mac GCC 4.9+, Clang 3.4+
C/C++ Windows 7+ Visual Studio 2015+
C# Linux, Mac .NET Core, Mono 4+
C# Windows 7+ .NET Core, NET 4.5+
Dart Windows, Linux, Mac Dart 2.2+
Go Windows, Linux, Mac Go 1.13+
Java Windows, Linux, Mac JDK 8 recommended (Jelly Bean+ for Android)
Kotlin/JVM Windows, Linux, Mac Kotlin 1.3+
Node.js Windows, Linux, Mac Node v8+
Objective-C macOS 10.10+, iOS 9.0+ Xcode 7.2+
PHP Linux, Mac PHP 7.0+
Python Windows, Linux, Mac Python 3.5+
Ruby Windows, Linux, Mac Ruby 2.3+

二、ASP.NET 中gRPC應用:

 1、建立gRPC服務專案:新建專案

  2、建立專案程式碼解析:

  如圖可以看到建立目錄中:主要新增:greet.proto、GreeterService

  a)greet.proto檔案說明:    

//指定協議緩衝區使用版本
syntax = "proto3";
//定義C#實現的名稱空間
option csharp_namespace = "GrpcServiceDemo";
//定義包名 package greet;
// 定義gRPC服務 service Greeter { //服務定義方法: rpc SayHello (HelloRequest) returns (HelloReply); } //引數型別定義 // The request message containing the user's name. message HelloRequest { string name = 1; } //相應結果型別定義 // The response message containing the greetings. message HelloReply { string message = 1; }

  b)gRPC服務實現:服務類 GreeterService ,服務類整合的 Greeter.GreeterBase 來自於根據proto檔案自動生成的,生成的類在 obj\Debug\netcoreapp3.1目錄下    

//Greeter.GreeterBase由grpc.tools根據proto檔案自動生成。
//檔案路徑在:obj\debug\netcoreapp3.1
public class GreeterService : Greeter.GreeterBase
{
    private readonly ILogger<GreeterService> _logger;
    public GreeterService(ILogger<GreeterService> logger)
    {
        _logger = logger;
    }
    public override Task<HelloReply> SayHello(HelloRequest request, ServerCallContext context)
    {
        return Task.FromResult(new HelloReply
        {
            Message = "Hello " + request.Name
        });
    }
}

  c)Startup檔案主要包括:

public class Startup
{
    // This method gets called by the runtime. Use this method to add services to the container.
    // For more information on how to configure your application, visit https://go.microsoft.com/fwlink/?LinkID=398940
    public void ConfigureServices(IServiceCollection services)
    {
        //注入Grpc服務
     services.AddGrpc(); } // This method gets called by the runtime. Use this method to configure the HTTP request pipeline. public void Configure(IApplicationBuilder app, IWebHostEnvironment env) { app.UseRouting(); app.UseEndpoints(endpoints => { //繫結服務實現介面 endpoints.MapGrpcService<GreeterService>(); //繫結預設節點輸出內容 endpoints.MapGet("/", async context => { await context.Response.WriteAsync("Communication with gRPC endpoints must be made through a gRPC client. To learn how to create a client, visit: https://go.microsoft.com/fwlink/?linkid=2086909"); }); }); } }

  d)專案檔案中新增了:

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

  e)配置檔案改變:指定以http2協議執行

  "Kestrel": {
    "EndpointDefaults": {
      "Protocols": "Http2"
    }
  }     

  3、建立自己的gRCP服務介面:在建立WebApi專案時預設建立了個天氣預報介面,那麼就來實現一個獲取天氣預報的gRPC服務

  a) 新增 weatherforecast.proto 檔案,定義服務介面

syntax = "proto3";

//匯入日期型別
import "google/protobuf/timestamp.proto";
//匯入空型別
import "google/protobuf/empty.proto";

//名稱空間
option csharp_namespace = "GrpcServiceDemo";

//包名稱
package weather;

//天氣服務
service Weather {
  //指定城市天氣
  rpc GetWeather (WeatherReques) returns (WeatherForecastInfo);

   //所有城市列表:入參為空
  rpc GetWeatherList (google.protobuf.Empty) returns (WeatherList);
}

//請求具體城市名稱
message WeatherReques {
  string name = 1;
}

//返回天氣資料列表
message WeatherList{
  repeated WeatherForecastInfo ListData =1;
}

//定義返回天氣資料型別
message WeatherForecastInfo {
  //日期時間型別
  google.protobuf.Timestamp Date = 1;
  int32 TemperatureC = 2;
  int32 TemperatureF = 3;
  string Summary = 4;
}

  b) 實現天氣獲取介面    

public class WeatherService : Weather.WeatherBase
{
    private static readonly string[] Summaries = new[] {"Freezing", "Bracing", "Chilly", "Cool", "Mild", "Warm", "Balmy", "Hot", "Sweltering", "Scorching"};

    private readonly ILogger<WeatherService> _logger;
    public WeatherService(ILogger<WeatherService> logger)
    {
        _logger = logger;
    }

    public override Task<WeatherForecastInfo> GetWeather(WeatherReques request, ServerCallContext context)
    {
        var rng = new Random();
        var result = new WeatherForecastInfo
        {
            //時間轉換
            Date = Timestamp.FromDateTimeOffset(new DateTimeOffset(DateTime.Now.AddDays(1))),
            TemperatureC = rng.Next(-20, 55),
            Summary = $"{Summaries[rng.Next(Summaries.Length)]}"
        };
        return Task.FromResult(result);
    }

    public override Task<WeatherList> GetWeatherList(Empty request, ServerCallContext context)
    {
        var rng = new Random();
        var data = Enumerable.Range(1, 5).Select(index => new WeatherForecastInfo
        {
            //時間轉換
            Date = Timestamp.FromDateTimeOffset(new DateTimeOffset(DateTime.Now.AddDays(1))),
            TemperatureC = rng.Next(-20, 55),
            Summary = $"{ Summaries[rng.Next(Summaries.Length)]}"
        });
        WeatherList weatherList = new WeatherList();
        weatherList.ListData.Add(data);
        return Task.FromResult(weatherList);
    }
}

  c)在 Startup終結點路由中註冊    

endpoints.MapGrpcService<WeatherService>();

  d)執行gRPC服務:

    

三、客戶端呼叫gRPC服務

 1、建立.net core控制檯應用;並新增nuget包引用  

Install-Package Grpc.Net.Client
Install-Package Google.Protobuf
Install-Package Grpc.Tools

 2、將服務端中Protos檔案,拷貝到客戶端中,並在專案檔案中新增以下內容,指定Grpc服務型別為:Client

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

 3、新增呼叫Grpc服務程式碼:

class Program
{
    static void Main(string[] args)
    {
        //初始化Grpc通道:引數為gRPC服務地址
        using var channel = GrpcChannel.ForAddress("https://localhost:5001");
        var client = new Greeter.GreeterClient(channel);
        var reply = client.SayHello(
                            new HelloRequest { Name = "GreeterClient" });

        Console.WriteLine("Greeting: " + reply.Message);

        //呼叫獲取天氣列表方法
        Console.WriteLine("呼叫獲取天氣列表方法");
        var wsClient = new Weather.WeatherClient(channel);
        var data = wsClient.GetWeatherList(new Empty());
        foreach (var item in data.ListData)
        {
            Console.WriteLine($"天氣資訊:城市:{item.Summary},時間:{item.Date},溫度:{item.TemperatureC},華氏度:{item.TemperatureF}");
        }
        //呼叫獲取天氣方法:帶引數
        Console.WriteLine("呼叫獲取天氣方法:帶引數");
        var result = wsClient.GetWeatherAsync(new WeatherRequest { Name = "Warm" }).ResponseAsync.Result;
        Console.WriteLine($"天氣資訊:城市:{result.Summary},時間:{result.Date},溫度:{result.TemperatureC},華氏度:{result.TemperatureF}");

        Console.WriteLine("Press any key to exit...");
        Console.ReadKey();
    }
}

 4、呼叫結果如下:

  

 四、總結

  到此已完成gRPC服務的搭建和呼叫示例,採用gRPC呼叫服務非常方便,可以直接呼叫服務方法。

  接下來還會進行更加深入的研究驗證。包括呼叫方式:服務端流式處理、客戶端流式處理、雙向流式處理等更加深入的用法

參考:

 官方說明文件:https://grpc.io/docs/what-is-grpc/ 

 微軟:https://docs.microsoft.com/zh-cn/aspnet/core/grpc/?view=aspnetcore-3.0

 示例原始碼地址:https://github.com/cwsheng/GrpcDemo

 

相關文章