众所周知,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 alivePooledConnectionIdleTimeout = Timeout.InfiniteTimeSpan,KeepAlivePingDelay = TimeSpan.FromSeconds(60),KeepAlivePingTimeout = TimeSpan.FromSeconds(30),// allows channel to add additional HTTP/2 connectionsEnableMultipleHttp2Connections = true};}); }); builder.Services.AddCodeFirstGrpcClient<IOrderService>(o => {o.Address = new Uri("http://localhost:5041/");o.ChannelOptionsActions.Add(options =>{options.HttpHandler = new SocketsHttpHandler(){// keeps connection alivePooledConnectionIdleTimeout = Timeout.InfiniteTimeSpan,KeepAlivePingDelay = TimeSpan.FromSeconds(60),KeepAlivePingTimeout = TimeSpan.FromSeconds(30),// allows channel to add additional HTTP/2 connectionsEnableMultipleHttp2Connections = 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