protobuf-net.Grpc 笔记
众所周知,Grpc很好用,但每次都需要手动编写 *.proto 文件,protobuf-net.Grpc个人感觉最大的优势是不用写*.proto 文件,相关教程如下:
https://learn.microsoft.com/zh-cn/aspnet/core/grpc/code-first?view=aspnetcore-8.0
https://protobuf-net.github.io/protobuf-net.Grpc/gettingstarted
1. 定义代码协定
[ServiceContract] public interface IGreeterService { [OperationContract] Task<HelloReply> SayHelloAsync(HelloRequest request); } [DataContract] public class HelloRequest { [DataMember(Order = 1)] public string Name { get; set; } } [DataContract] public class HelloReply { [DataMember(Order = 1)] public string Message { get; set; } } [Service] public interface IOrderService { CreateResult CreateOrder(CreateRequest request); QueryResult QueryOrder(QueryRequest request); } [ProtoContract] public class CreateRequest { [ProtoMember(1)] public string OrderNo { get; set; } [ProtoMember(2)] public string OrderName { get; set; } [ProtoMember(3)] public string Price { get; set; } } [ProtoContract] public class CreateResult { [ProtoMember(1)] public bool Result { get; set; } [ProtoMember(2)] public string Message { get; set; } } [ProtoContract] public class QueryRequest { [ProtoMember(1)] public int Id { get; set; } } [ProtoContract] public class QueryResult { [ProtoMember(1)] public int Id { get; set; } [ProtoMember(2)] public string OrderNo { get; set; } [ProtoMember(3)] public string OrderName { get; set; } [ProtoMember(4)] public double Price { get; set; } }
前面的代码,SayHello 部分定义了HelloRequest、HelloReply消息 和 使用一元 SayHelloAsync gRPC 方法定义 IGreeterService 协定接口
代码如下:https://gitee.com/Karl_Albright/csharp-demo/tree/master/GrpcDemo/ProtobufNetShared
2. 定义Grpc服务
创建 ASP.NET Core Web API 项目,名称为ProtobufNetService,安装 protobuf-net.Grpc.AspNetCore 和 引用 ProtobufNetShared
创建 GreeterService 并实现 IGreeterService,创建 OrderService 并实现 IOrderService
public class GreeterService : IGreeterService { public Task<HelloReply> SayHelloAsync(HelloRequest request) { return Task.FromResult(new HelloReply { Message = "你好 " + request.Name }); } } public class OrderService : IOrderService { public CreateResult CreateOrder(CreateRequest request) { return new CreateResult { Result = true, Message = "订单创建成功", }; } public QueryResult QueryOrder(QueryRequest request) { return new QueryResult { Id = request.Id, OrderNo = DateTime.Now.ToString("yyyyMMddHHmmss"), OrderName = "冰箱", Price = 1288 }; } }
更新 Program 文件
public class Program { public static void Main(string[] args) { var builder = WebApplication.CreateBuilder(args); builder.Services.AddCodeFirstGrpc(); var app = builder.Build(); app.MapGrpcService<GreeterService>(); app.MapGrpcService<OrderService>(); app.MapGet("/", () => "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"); app.Run(); } }
3. 创建 Grpc客户端
创建控制台项目,名称叫 ProtobufNetDemo,安装 Grpc.Net.Client 和 protobuf-net.Grpc
更新 Program.cs 代码
internal class Program { static async Task Main(string[] args) { using var channel = GrpcChannel.ForAddress("http://localhost:5041"); var client = channel.CreateGrpcService<IGreeterService>(); var reply = await client.SayHelloAsync( new HelloRequest { Name = "Karl" }); Console.WriteLine($"Greeting: {reply.Message}"); Console.WriteLine("Press any key to exit..."); Console.ReadKey(); } }
代码如下:https://gitee.com/Karl_Albright/csharp-demo/tree/master/GrpcDemo/ProtobufNetDemo
先运行 ProtobufNetService,再运行 ProtobufNetDemo 运行结果如下
4. 创建 Web api 客户端
创建 ASP.NET Core Web API 项目,名称为ProtobufNetClient,安装 protobuf-net.Grpc.AspNetCore、protobuf-net.Grpc.ClientFactory 和 引用 ProtobufNetShared
增加 Program.cs 代码
builder.Services.AddCodeFirstGrpcClient<IGreeterService>(o => { o.Address = new Uri("http://localhost:5041/"); o.ChannelOptionsActions.Add(options => { options.HttpHandler = new SocketsHttpHandler() { // keeps connection alive PooledConnectionIdleTimeout = Timeout.InfiniteTimeSpan, KeepAlivePingDelay = TimeSpan.FromSeconds(60), KeepAlivePingTimeout = TimeSpan.FromSeconds(30), // allows channel to add additional HTTP/2 connections EnableMultipleHttp2Connections = true }; }); }); builder.Services.AddCodeFirstGrpcClient<IOrderService>(o => { o.Address = new Uri("http://localhost:5041/"); o.ChannelOptionsActions.Add(options => { options.HttpHandler = new SocketsHttpHandler() { // keeps connection alive PooledConnectionIdleTimeout = Timeout.InfiniteTimeSpan, KeepAlivePingDelay = TimeSpan.FromSeconds(60), KeepAlivePingTimeout = TimeSpan.FromSeconds(30), // allows channel to add additional HTTP/2 connections EnableMultipleHttp2Connections = true }; }); });
创建 HelloController 和 OrderController
[ApiController] [Route("[controller]/[action]")] public class HelloController : ControllerBase { IGreeterService service; public HelloController(IGreeterService service) { this.service = service; } [HttpGet(Name = "Echo")] public string Echo(string name) { return service.SayHelloAsync(new HelloRequest { Name = name }).Result.Message; } }
[ApiController] [Route("[controller]/[action]")] public class OrderController : ControllerBase { IOrderService service; public OrderController(IOrderService service) { this.service = service; } [HttpGet(Name = "CreateOrder")] public CreateResult CreateOrder() { return service.CreateOrder(new CreateRequest { OrderNo = DateTime.Now.ToString("yyyyMMddHHmmss"), OrderName = "订单名称", Price = "12.32" }); } [HttpGet(Name = "QueryOrder")] public QueryResult QueryOrder(int id) { return service.QueryOrder(new QueryRequest { Id = id, }); } }
代码地址: https://gitee.com/Karl_Albright/csharp-demo/tree/master/GrpcDemo/ProtobufNetClient
先运行 ProtobufNetService,再运行 ProtobufNetClient 运行结果如下,在Swagger中调用相应的Api