最近公司新项目选项觉得使用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包。