最近公司新項目選項覺得使用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包。