使用 .NET 的代码优先 gRPC 服务和客户端
当整个系统使用 .NET 时,代码优先是一个不错的选择:
- 可以在 .NET 服务器和客户端之间共享 .NET 服务和数据协定类型。
- 无需在
.proto
文件和代码生成过程中定义协定。
不建议在具有多种语言的 polyglot 系统中使用代码优先。 .NET 服务和数据协定类型不能与非 .NET 平台一起使用。 其他平台若要调用使用代码优先编写的 gRPC 服务,必须创建一个与该服务匹配的 .proto
协定。
1.使用protobuf-net.Grpc创建接口
protobuf-net.Grpc 是一个社区项目,不受 Microsoft 支持。 它将对 Grpc.AspNetCore
和 Grpc.Net.Client
添加代码优先支持。 它使用通过属性批注的 .NET 类型来定义应用的 gRPC 服务和消息。
using ProtoBuf.Grpc; using System.Runtime.Serialization; using System.ServiceModel; using System.Threading.Tasks; namespace Shared.Contracts; [DataContract] public class HelloReply { [DataMember(Order = 1)] public string Message { get; set; } } [DataContract] public class HelloRequest { [DataMember(Order = 1)] public string Name { get; set; } } [ServiceContract] public interface IGreeterService { [OperationContract] Task<HelloReply> SayHelloAsync(HelloRequest request, CallContext context = default); }
前面的代码:
- 定义
HelloRequest
和HelloReply
消息。 - 定义
IGreeterService
协定接口。
服务协定在服务器上实现并从客户端调用。
2.创建 gRPC 服务端
若要将 gRPC 代码优先服务添加到 ASP.NET Core 应用,请执行以下步骤:
-
添加一个 protobuf-net.Grpc.AspNetCore 包引用。
-
创建一个新的
GreeterService.cs
文件并实现IGreeterService
服务接口:using Shared.Contracts; using ProtoBuf.Grpc; public class GreeterService : IGreeterService //引用第一步的接口 { public Task<HelloReply> SayHelloAsync(HelloRequest request, CallContext context = default) { return Task.FromResult( new HelloReply { Message = $"Hello {request.Name}" }); } }
更新
Program.cs
文件: -
using ProtoBuf.Grpc.Server; var builder = WebApplication.CreateBuilder(args); // 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 // Add services to the container. builder.Services.AddCodeFirstGrpc(); var app = builder.Build(); // Configure the HTTP request pipeline. app.MapGrpcService<GreeterService>(); 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();
前面突出显示的代码更新以下内容:
AddCodeFirstGrpc
注册启用了代码优先的服务。MapGrpcService<GreeterService>
添加代码优先的服务终结点。
3.创建代码优先 gRPC 客户端
代码优先 gRPC 客户端使用服务协定来调用 gRPC 服务。
-
在 gRPC 客户端
.csproj
文件中:- 添加一个 protobuf-net.Grpc 包引用。
- 添加 Grpc.Net.Client 包引用。
-
更新客户端
program.cs
// See https://aka.ms/new-console-template for more information using Grpc.Net.Client; using ProtoBuf.Grpc.Client; using Shared.Contracts; namespace GrpcGreeterClient; internal class Program { private static async Task Main(string[] args) { using var channel = GrpcChannel.ForAddress("https://localhost:7184"); var client = channel.CreateGrpcService<IGreeterService>();//引用第一步的接口 var reply = await client.SayHelloAsync( new HelloRequest { Name = "GreeterClient" }); Console.WriteLine($"Greeting: {reply.Message}"); Console.WriteLine("Press any key to exit..."); Console.ReadKey(); } }
前面的 gRPC 客户端 Program.cs
代码执行以下操作:
- 创建一个 gRPC channel。
- 使用
CreateGrpcService<IGreeterService>
扩展方法从通道创建代码优先客户端。 - 使用
SayHelloAsync
调用 gRPC 服务。