歡迎光臨
每天分享高質量文章

ASP.NET Core 3.0 上的gRPC服務模板初體驗(多圖)

早就聽說ASP.NET Core 3.0中引入了gRPC的服務模板,正好趁著家裡電腦剛做了新系統,然後裝了VS2019的功夫來體驗一把。同時記錄體驗的過程。如果你也想按照本文的步驟體驗的話,那你得先安裝.NET Core3.0預覽版的SDK。至於開發工具我用的時VS2019,當然你也可以使用VS Code進行。

作者:依樂祝
原文地址:https://www.cnblogs.com/yilezhu/p/10631420.html

gRPC的簡單介紹

gRPC 是一種與語言無關的高效能遠端過程呼叫 (RPC) 框架。 有關 gRPC 基礎知識的詳細資訊,請參閱 gRPC 檔案頁。

gRPC 的主要優點是:

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

這些優點使 gRPC 適用於:

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

ASP.NET Core 3.0上gRPC服務模板初體驗

建立gRPC服務

  1. 開啟VS2019 從 Visual Studio“檔案”選單中選擇“新建” > “專案”。(由於我是新開啟的VS,所以按照如下圖所示建立新專案)

  2. 如下圖所示,選擇建立《ASP.NET Core Web 應用程式》,然後點選下一步

  3. 在此頁面按照下圖所示,輸入專案名稱,位置,解決方案名稱,然後點選右下角的“建立”按鈕進行建立。

  4. 你以為上述步驟中點選“建立”就結束了嘛?說好的要建立gRPC服務模板的,所以,點選上面的建立後會彈出如下圖所示,讓你選擇服務模板的視窗,這裡按照下圖所示選擇gRPC服務模板,然後再次點選右下角的建立,才是真正的建立專案。

  5. 建立成功後,會出現如下圖所示的專案結構

  6. 至此,我們就建立好了一個gRPC服務的模板,接下來我們先測試一番,然後再好好的看下這個模板的結構吧

測試gRPC服務

  1. 首先開啟HelloGrpc.Server 這個服務端的工作目錄,然後Shift+滑鼠右鍵彈出如下圖所示的右鍵選單,如圖所示開啟ps視窗

  2. 輸入dotnet run 命令執行此gRPC服務端專案,如下圖所示,說明服務端啟動正常,並開始監聽對應的埠。

  3. 同樣的方法,我們啟動客戶端,這時候客戶端會向該服務端傳送一條包含具有其名稱“GreeterClient”的訊息的問候資訊。 該服務端將傳送一條訊息“Hello GreeterClient”作為響應,並顯示在命令提示符中。如下圖所示:

  4. 至此,gRPC服務模板建立的服務端以及客戶端測試成功。下麵我們就好好的探究一下這個服務模板吧。

gRPC模板解析

HelloGrpc.Server 服務的端專案中有如下幾個檔案

  • greet.proto:greet.proto 檔案定義 Greeter gRPC,且用於生成 gRPC 伺服器資產。
  • Services 檔案夾:包含 Greeter 服務的實現。
  • appSettings.json:包含配置資料,如 Kestrel 使用的協議。(熟悉ASP.NET Core的你一定很熟悉)
  • Program.cs:包含 gRPC 服務的入口點。(熟悉ASP.NET Core的你一定很熟悉)
  • Startup.cs:IWebHostBuilder的啟動配置檔案,包含配置應用行為的程式碼。(熟悉ASP.NET Core的你一定很熟悉)

gRPC 客戶端 HelloGrpc.Client 檔案:

Program.cs 包含 gRPC 客戶端的入口點和邏輯。

下麵我們再開啟每個檔案看看裡面究竟是什麼東東吧。

proto檔案

proto

GRPC使用約定優先的API開發方法。預設情況下,使用協議緩衝區(Protobuf)作為介面設計語言(IDL)。這個.proto檔案包含:

  • GRPC服務的定義。
  • 在客戶端和伺服器之間傳送的訊息。

有關Protobuf檔案語法的更多資訊,請參見正式檔案(原型).

如我們模板中建立的greet.proto 檔案內容如下:

syntax = "proto3";

package Greet;

// The greeting service definition.
service Greeter {
  // Sends a greeting
  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;
}
  • 定義Greeter服務。
  • 這個Greeter服務定義SayHello請求。
  • SayHello傳送HelloRequest訊息並接收HelloResponse資訊:
    那麼你可能要問了,這個.proto檔案是如何包含在專案中的呢,其實,如果你開啟.csproject檔案就會看到,透過將該檔案新增到的ItemGroup中即可,如下所示:
<ItemGroup>
  <Protobuf Include="..\Protos\*.proto" GrpcServices="Server" />
  <Content Include="@(Protobuf)" LinkBase="" />
ItemGroup>

C#對.proto檔案的工具支援

工具包Grpc.Tools 被用來從.proto檔案生成C#檔案。生成的資產(檔案)具有如下特性:

  • 每次構建專案時都會根據需要進行生成。
  • 生成的檔案不會被新增到專案或簽入原始碼管理。
  • 生成的C#檔案是包含在OBJ目錄。

伺服器和客戶端專案都需要此包。Grpc.Tools可以透過在VisualStudio中使用包管理器或新增到專案檔案:

XML複製

<PackageReference Include="Grpc.Tools" Version="1.19.0-pre1" PrivateAssets="All" />

工具包在執行時並不是必需的,因此,應該用PrivateAssets="All".

Services 檔案夾中的具體的gRPC服務

我們知道Grpc.Tools工具包將根據.proto檔案的定義翻譯並生成對應的C#型別的檔案。

對於伺服器端資產,將生成一個抽象的服務基型別。基型別包含在.proto檔案中包含的所有GRPC呼叫的定義。然後,您將建立從此基型別派生的具體服務實現,並實現GRPC呼叫的邏輯。對於前面描述的greet.proto示例,將生成包含虛擬SayHello方法的抽象GreeterBase型別。具體的實現GreeterService重寫該方法並實現處理GRPC呼叫的邏輯。
正如HelloGrpc.Server專案中的Services\GreeterService.cs中的程式碼

public class GreeterService : Greeter.GreeterBase
{
    public override Task 
        SayHello(HelloRequest request, ServerCallContext context)
    {
        return Task.FromResult(new HelloReply
        {
            Message = "Hello " + request.Name
        });
    }
}

對於客戶端,將生成一個具體的客戶端型別中的GRPC呼叫。.proto檔案被轉換為可以呼叫的具體型別上的方法。為greet.proto前面描述的示例,一個具體的GreeterClient型別生成。這個GreeterClient型別包含SayHello方法,可以呼叫該方法來啟動對伺服器的GRPC呼叫。

public class Program
{
    static async Task Main(string[] args)
    {
        // Include port of the gRPC server as an application argument
        var port = args.Length > 0 ? args[0] : "50051";

        var channel = new Channel("localhost:" + port, ChannelCredentials.Insecure);
        var client = new Greeter.GreeterClient(channel);

        var reply = await client.SayHelloAsync(
                                      new HelloRequest { Name = "GreeterClient" });
        Console.WriteLine("Greeting: " + reply.Message);

        await channel.ShutdownAsync();

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

預設情況下,分別生成伺服器和客戶端資產。.proto檔案包含在專案組。若要確保僅在伺服器專案中生成伺服器資產,GrpcServices屬性設定為Server.

XML複製

<ItemGroup>
  <Protobuf Include="..\Protos\*.proto" GrpcServices="Server" />
  <Content Include="@(Protobuf)" LinkBase="" />
ItemGroup>

類似地,屬性設定為Client在僅在客戶專案中生成。

Startup

Startup中我們發現跟普通的ASP.NET Core程式有所不同,具體的如下圖所示:在ConfigureServices 服務中引入了gRPC服務,然後在Configure加入了路由

而這裡需要引入三個與gRPC相關的nuget包

  • Grpc.AspNetCore.Server
  • Google.Protobuf對於Protobuf訊息API。
  • Grpc.Tools

這裡需要說明的是

ASP.NET Core 中介軟體和功能共享路由管道,因此可以將應用程式配置為服務其他請求處理程式。其他請求處理程式(如MVC控制器)可以與配置的GRPC服務路由並行工作。

其他需要說明的內容

與ASP.NET Core 介面的整合

GRPC服務可以完全訪問ASP.NETCore功能,如依賴註入(Di)和日誌功能。例如,服務實現可以透過建構式解析DI容器中的記錄器服務:

public class GreeterService : Greeter.GreeterBase
{
    public GreeterService(ILogger logger)
    {
    }
}

預設情況下,GRPC服務可以解析具有任意生存期的其他DI服務(Singleton, Scoped, or Transient)。

在GRPC方法中解析HttpContext

GRPC 應用程式介面提供對某些HTTP/2訊息資料的訪問,例如method, host, essay-header, and trailers。訪問是透過ServerCallContext引數傳遞給每個GRPC方法:

public class GreeterService : Greeter.GreeterBase
{
    public override Task 
        SayHello(HelloRequest request, ServerCallContext context)
    {
        return Task.FromResult(new HelloReply
        {
            Message = "Hello " + request.Name
        });
    }
}

ServerCallContext不提供對所有ASP.NET 介面中HttpContext的完全訪問。GetHttpContext擴充套件方法提供對錶示ASP.NET API中底層HTTP/2訊息的httpContext的完全訪問:

public class GreeterService : Greeter.GreeterBase
{
    public override Task SayHello(HelloRequest request, 
        ServerCallContext context)
    {
        var httpContext = context.GetHttpContext();

        return Task.FromResult(new HelloReply
        {
            Message = "Using https: " + httpContext.Request.IsHttps
        });
    }
}

請求體資料速率限制

預設情況下,Kestrel伺服器設定為最小請求主體資料速率。對於客戶端流式和雙工流式的請求,此速率可能不滿足,並且連線可能超時。當GRPC服務包括客戶端流和雙工流呼叫時,必須禁用最小請求正文資料速率限制:

public class Program
{
    public static void Main(string[] args)
    {
        CreateHostBuilder(args).Build().Run();
    }

    public static IHostBuilder CreateHostBuilder(string[] args) =>
         Host.CreateDefaultBuilder(args)
    .ConfigureWebHostDefaults(webBuilder =>
    {
        webBuilder.UseStartup();
        webBuilder.ConfigureKestrel((context, options) =>
        {
            options.Limits.MinRequestBodyDataRate = null;
        });
    });
}

參考文章

  • gRPC services with C#
  • Tutorial: Get started with gRPC in ASP.NET Core
  • gRPC services with ASP.NET Core
  • Migrating gRPC services from C-core to ASP.NET Core

總結

今天分享的內容有點多,目的就是使記錄盡可能的詳細,盡可能用通俗易懂的語言來進行描述,讓大家能用起來。在asp.net core3.0中把grpc服務作為第一等公民進行支援,所以我們有必要進行下瞭解。可能很多朋友會有疑問了,我Web API用的爽歪歪,幹嘛還要用gRPC這種遠端過程呼叫協議啊。關於這個問題,我準備再單獨開一篇文章進行講解,最後感謝大家的閱讀,碼字不易,多多推薦支援吧!

 

    贊(0)

    分享創造快樂