使用 C# 的 gRPC 服务gRPC services with C

本文内容

本文档概述在 C# 中编写 gRPC 应用所需的概念。此处涵盖的主题适用于基于 C-core 和基于 ASP.NET Core 的 gRPC 应用。

proto 文件proto file

gRPC 使用协定优先方法进行 API 开发。默认情况下,协议缓冲区 (protobuf) 用作接口设计语言 (IDL)。*.proto 文件包含:

  • gRPC 服务的定义。
  • 在客户端与服务器之间发送的消息。

有关 protobuf 文件的语法的详细信息,请参阅官方文档 (protobuf)

例如,请考虑开始使用 gRPC 服务中使用的 greet.proto 文件:

  • 定义 Greeter 服务。
  • Greeter 服务定义 SayHello 调用。
  • SayHello 发送 HelloRequest 消息并接收 HelloReply 消息:
  1. syntax = "proto3";
  2. option csharp_namespace = "GrpcGreeter";
  3. package greet;
  4. // The greeting service definition.
  5. service Greeter {
  6. // Sends a greeting
  7. rpc SayHello (HelloRequest) returns (HelloReply);
  8. }
  9. // The request message containing the user's name.
  10. message HelloRequest {
  11. string name = 1;
  12. }
  13. // The response message containing the greetings.
  14. message HelloReply {
  15. string message = 1;
  16. }

若要查看翻译为非英语语言的代码注释,请在 此 GitHub 讨论问题中告诉我们。

将 .proto 文件添加到 C# 应用Add a .proto file to a C# app

通过将 *.proto 文件添加到 <Protobuf> 项组中,可将该文件包含在项目中:

  1. <ItemGroup>
  2. <Protobuf Include="Protos\greet.proto" GrpcServices="Server" />
  3. </ItemGroup>

.proto 文件的 C# 工具支持C# Tooling support for .proto files

需要工具包 Grpc.Tools 才能从 *.proto 文件生成 C# 资产。生成的资产(文件):

  • 在每次生成项目时按需生成。
  • 不会添加到项目中或是签入到源代码管理中。
  • 是包含在 obj 目录中的生成工件。

服务器和客户端项目都需要此包。Grpc.AspNetCore 元包中包含对 Grpc.Tools 的引用。服务器项目可以使用 Visual Studio 中的包管理器或通过将 <PackageReference> 添加到项目文件来添加 Grpc.AspNetCore

  1. <PackageReference Include="Grpc.AspNetCore" Version="2.23.2" />

客户端项目应直接引用 Grpc.Tools 以及使用 gRPC 客户端所需的其他包。运行时不需要工具包,因此依赖项标记为 PrivateAssets="All"

  1. <PackageReference Include="Google.Protobuf" Version="3.9.2" />
  2. <PackageReference Include="Grpc.Net.Client" Version="2.23.2" />
  3. <PackageReference Include="Grpc.Tools" Version="2.23.0" PrivateAssets="All" />

生成的 C# 资产Generated C# assets

工具包会生成表示在所包含 *.proto 文件中定义的消息的 C# 类型。

对于服务器端资产,会生成抽象服务基类型。基类型包含 .proto 文件中包含的所有 gRPC 调用的定义。创建一个派生自此基类型并为 gRPC 调用实现逻辑的具体服务实现。对于 greet.proto(前面所述的示例),会生成一个包含虚拟 SayHello 方法的抽象 GreeterBase 类型。具体实现 GreeterService 会替代该方法,并实现处理 gRPC 调用的逻辑。

  1. public class GreeterService : Greeter.GreeterBase
  2. {
  3. public override Task<HelloReply> SayHello(
  4. HelloRequest request, ServerCallContext context)
  5. {
  6. return Task.FromResult(new HelloReply
  7. {
  8. Message = "Hello " + request.Name
  9. });
  10. }
  11. }

对于客户端资产,会生成一个具体客户端类型。.proto 文件中的 gRPC 调用会转换为具体类型中的方法,可以进行调用。对于 greet.proto(前面所述的示例),会生成一个 GreeterClient 类型。调用 GreeterClient.SayHelloAsync 以发起对服务器的 gRPC 调用。

  1. static async Task Main(string[] args)
  2. {
  3. // The port number(5001) must match the port of the gRPC server.
  4. using var channel = GrpcChannel.ForAddress("https://localhost:5001");
  5. var client = new Greeter.GreeterClient(channel);
  6. var reply = await client.SayHelloAsync(
  7. new HelloRequest { Name = "GreeterClient" });
  8. Console.WriteLine("Greeting: " + reply.Message);
  9. Console.WriteLine("Press any key to exit...");
  10. Console.ReadKey();
  11. }

默认情况下,会为 <Protobuf> 项组中包含的每个 *.proto 文件都生成服务器和客户端资产。若要确保服务器项目中仅生成服务器资产,请将 GrpcServices 属性设置为 Server

  1. <ItemGroup>
  2. <Protobuf Include="Protos\greet.proto" GrpcServices="Server" />
  3. </ItemGroup>

同样,该属性在客户端项目中设置为 Client

Azure 应用服务不支持 gRPCgRPC not supported on Azure App Service

警告

Azure 应用服务或 IIS 当前不支持 ASP.NET Core gRPCHttp.Sys 的 HTTP/2 实现不支持 gRPC 依赖的 HTTP 响应尾随标头。有关详细信息,请参阅此 GitHub 问题

其他资源Additional resources