1. 程式人生 > 其它 >Grpc系列(一):Net5使用Grpc

Grpc系列(一):Net5使用Grpc

最近公司新專案選項覺得使用GRPC,因為之前沒怎麼接觸過,所以覺得研究記錄一下使用過程,話不多說,我們第一步先在專案裡配置一下。

新建AspNetCoreGrpc Api專案,Nuget安裝 Grpc.AspNetCore 包,Startup類裡新增gRPC services:

services.AddGrpc();

然後新增Protos資料夾和PB協議檔案HelloTest.proto:

syntax = "proto3";

option csharp_namespace = "AspNetCoregRpcService";

import "google/protobuf/empty.proto
"; package HelloGrpcTest; //定義包名 //定義服務 //定義方法 service HelloTest{ rpc SayHello(SayHelloRequest) returns(SayHelloResult); } message SayHelloRequest{ string Name=1; } //定義返回值 message SayHelloResult{ string message=1; }

這裡添加了一個名為HelloTest的服務和名為SayHello的方法,有一個入參並且有一個返回類SayHelloResult,

然後我們需要在csproj 專案檔案裡,包含對 proto 檔案引用:

<Project Sdk="Microsoft.NET.Sdk.Web">

  <PropertyGroup>
    <TargetFramework>netcoreapp3.1</TargetFramework>
  </PropertyGroup>

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

  <ItemGroup>
    <PackageReference Include="
Grpc.AspNetCore" Version="2.27.0" /> </ItemGroup> </Project>

然後我們新增服務的實現,新增Services資料夾和HelloTestService.cs實現類:

using AspNetCoregRpcService;
using Grpc.Core;
using System.Threading.Tasks;

namespace AspNetCoreGrpc.Services
{
    public class HelloTestService: HelloTest.HelloTestBase
    {
        public override Task<SayHelloResult> SayHello(SayHelloRequest request, ServerCallContext context)
        {
            var result = new SayHelloResult { Message = $"Hi,My name is {request.Name}!" };

            return Task.FromResult(result);
        }
    }
}

接著我們需要在Startup.cs的Configure方法裡配置Map:

public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
        {
            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
            }

            app.UseRouting();

            app.UseEndpoints(endpoints =>
            {
                endpoints.MapGrpcService<HelloTestService>();
                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");
                });
            });
        }

最後我們需要在appsettings.json配置使用HTTP2,因為GRPC使用HTTP2通訊:

{
  "Logging": {
    "LogLevel": {
      "Default": "Information",
      "Microsoft": "Warning",
      "Microsoft.Hosting.Lifetime": "Information"
    }
  },
  "AllowedHosts": "*",
  "Kestrel": {
    "EndpointDefaults": {
      "Protocols": "Http2"
    }
  }
}

到這裡GRPC服務端我們已經寫好並且能夠測試使用了,但是在實際生產中我們要測試一個方法或者介面通常是在swagger直接呼叫的,那麼是不是可以讓GRPC也支援swagger呢,這個也是可以的,但是我們需要了解到,swagger走的是HTTP呼叫,那就意味著我們需要對服務進行HTTP和GRPC兩種支援,所以這裡的解決方案是監聽兩個埠,分別支援HTTP和GRPC,我們需要接著做一點改動:

Nuget引入Microsoft.AspNetCore.Grpc.HttpApi、Microsoft.AspNetCore.Grpc.Swagger包,需要勾選預覽版,還沒發正式版,並替換Startup.cs裡的方法:

        // 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)
        {
            services.AddGrpcHttpApi();

            services.AddSwaggerGen(c =>
            {
                c.SwaggerDoc("v1", new OpenApiInfo { Title = "AspNetCoreGrpc.api", Version = "v1" });
            });

            services.AddGrpcSwagger();
        }

        // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
        public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
        {
            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
            }

            app.UseSwagger();

            app.UseSwaggerUI(c => c.SwaggerEndpoint("/swagger/v1/swagger.json", "AspNetCoreGrpc v1"));

            app.UseRouting();

            app.UseEndpoints(endpoints =>
            {
                endpoints.MapGrpcService<HelloTestService>();
                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");
                });
            });
        }

這裡我們需要因為兩個google的PB協議檔案,所以大家需要下載一下:

https://github.com/aspnet/AspLabs/blob/c1e59cacf7b9606650d6ec38e54fa3a82377f360/src/GrpcHttpApi/sample/Proto/google/api/http.proto

https://github.com/aspnet/AspLabs/blob/c1e59cacf7b9606650d6ec38e54fa3a82377f360/src/GrpcHttpApi/sample/Proto/google/api/annotations.proto

放到google/api資料夾下就可以:

同時我們需要修改我們的HelloTest.proto協議檔案配置路由:

syntax = "proto3";

option csharp_namespace = "AspNetCoregRpcService";

import "google/api/annotations.proto";

package HelloGrpcTest; //定義包名

//定義服務
//定義方法
service HelloTest{
    rpc SayHello(SayHelloRequest) returns(SayHelloResult){
        option (google.api.http) = {
        post: "/SayHello"
        body: "*"
        };
    };
}

message SayHelloRequest{
    string Name=1;
}


//定義返回值
message SayHelloResult{
    string message=1;
}

最後也是最關鍵的一步,設定分別監聽HTTP1和HTTP2埠:

using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Server.Kestrel.Core;
using Microsoft.Extensions.Hosting;

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

        // Additional configuration is required to successfully run gRPC on macOS.
        // For instructions on how to configure Kestrel and gRPC clients on macOS, visit https://go.microsoft.com/fwlink/?linkid=2099682
        public static IHostBuilder CreateHostBuilder(string[] args) =>
            Host.CreateDefaultBuilder(args)
                .ConfigureWebHostDefaults(webBuilder =>
                {
                    webBuilder.UseUrls().UseKestrel((host, options) =>
                    {
                        options.ListenAnyIP(50051, o => o.Protocols = HttpProtocols.Http2);
                        options.ListenAnyIP(8081, o => o.Protocols = HttpProtocols.Http1);
                    });

                    webBuilder.UseStartup<Startup>();
                });
    }
}

然後我們再改一下launchSettings.json指定8081埠就可以運行了:

{
  "profiles": {
    "AspNetCoreGrpc": {
      "commandName": "Project",
      "launchBrowser": false,
      "applicationUrl": "https://localhost:8081",
      "environmentVariables": {
        "ASPNETCORE_ENVIRONMENT": "Development"
      }
    }
  }
}

啟動執行然後瀏覽器打到http://localhost:8081/swagger/index.html 看下:

看起來沒問題了,那麼客戶端該如何使用呢,只要把Protos檔案拷貝到客戶端專案裡就可以了,當然常用方法是釋出Nuget包。