使用 C# 的 gRPC 服务
注意
此版本不是本文的最新版本。 有关当前版本,请参阅本文的 .NET 9 版本。
警告
此版本的 ASP.NET Core 不再受支持。 有关详细信息,请参阅 .NET 和 .NET Core 支持策略。 对于当前版本,请参阅此文的 .NET 8 版本。
本文档概述在 C# 中编写 gRPC 应用所需的概念。 此处涵盖的主题适用于基于 C-core 和基于 ASP.NET Core 的 gRPC 应用。
proto 文件
gRPC 使用协定优先方法进行 API 开发。 默认情况下,协议缓冲区 (protobuf) 用作接口定义语言 (IDL)。 .proto
文件包含:
- gRPC 服务的定义。
- 在客户端与服务器之间发送的消息。
有关 protobuf 文件的语法的详细信息,请参阅为 .NET 应用创建 Protobuf 消息。
例如,请考虑开始使用 gRPC 服务中使用的 greet.proto 文件:
- 定义
Greeter
服务。 Greeter
服务定义SayHello
调用。SayHello
发送HelloRequest
消息并接收HelloReply
消息:
syntax = "proto3";
option csharp_namespace = "GrpcGreeter";
package greet;
// The greeting service definition.
service Greeter {
// Sends a greeting
rpc SayHello (HelloRequest) returns (HelloReply);
}
// The request message containing the user's name.
message HelloRequest {
string name = 1;
}
// The response message containing the greetings.
message HelloReply {
string message = 1;
}
若要查看翻译为非英语语言的代码注释,请在 此 GitHub 讨论问题中告诉我们。
将 .proto
文件添加到 C# 应用
通过将 .proto
文件添加到 <Protobuf>
项组中,可将该文件包含在项目中:
<ItemGroup>
<Protobuf Include="Protos\greet.proto" GrpcServices="Server" />
</ItemGroup>
默认情况下,<Protobuf>
引用将生成具体的客户端和服务基类。 可使用引用元素的 GrpcServices
特性来限制 C# 资产生成。 有效 GrpcServices
选项如下:
Both
(如果不存在,则为默认值)Server
Client
None
对 .proto
文件的 C# 工具支持
需要工具包 Grpc.Tools 才能从 .proto
文件生成 C# 资产。 生成的资产(文件):
- 在每次生成项目时按需生成。
- 不会添加到项目中或是签入到源代码管理中。
- 是包含在 obj 目录中的生成工件。
服务器和客户端项目都需要此包。 Grpc.AspNetCore
元包中包含对 Grpc.Tools
的引用。 服务器项目可以使用 Visual Studio 中的包管理器或通过将 <PackageReference>
添加到项目文件来添加 Grpc.AspNetCore
:
<PackageReference Include="Grpc.AspNetCore" Version="2.32.0" />
客户端项目应直接引用 Grpc.Tools
以及使用 gRPC 客户端所需的其他包。 运行时不需要工具包,因此依赖项标记为 PrivateAssets="All"
:
<PackageReference Include="Google.Protobuf" Version="3.18.0" />
<PackageReference Include="Grpc.Net.Client" Version="2.52.0" />
<PackageReference Include="Grpc.Tools" Version="2.40.0">
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
<PrivateAssets>all</PrivateAssets>
</PackageReference>
生成的 C# 资产
工具包会生成表示在所包含 .proto
文件中定义的消息的 C# 类型。
对于服务器端资产,会生成抽象服务基类型。 基类型包含 .proto
文件中所含的所有 gRPC 调用的定义。 创建一个派生自此基类型并为 gRPC 调用实现逻辑的具体服务实现。 对于 greet.proto
(前面所述的示例),会生成一个包含虚拟 SayHello
方法的抽象 GreeterBase
类型。 具体实现 GreeterService
会替代该方法,并实现处理 gRPC 调用的逻辑。
public class GreeterService : Greeter.GreeterBase
{
private readonly ILogger<GreeterService> _logger;
public GreeterService(ILogger<GreeterService> logger)
{
_logger = logger;
}
public override Task<HelloReply> SayHello(HelloRequest request, ServerCallContext context)
{
return Task.FromResult(new HelloReply
{
Message = "Hello " + request.Name
});
}
}
对于客户端资产,会生成一个具体客户端类型。 .proto
文件中的 gRPC 调用会转换为具体类型中的方法,可以进行调用。 对于 greet.proto
(前面所述的示例),会生成一个 GreeterClient
类型。 调用 GreeterClient.SayHelloAsync
以发起对服务器的 gRPC 调用。
// The port number must match the port of the gRPC server.
using var channel = GrpcChannel.ForAddress("https://localhost:7042");
var client = new Greeter.GreeterClient(channel);
var reply = await client.SayHelloAsync(
new HelloRequest { Name = "GreeterClient" });
Console.WriteLine("Greeting: " + reply.Message);
Console.WriteLine("Press any key to exit...");
Console.ReadKey();
默认情况下,会为 <Protobuf>
项组中包含的每个 .proto
文件都生成服务器和客户端资产。 若要确保服务器项目中仅生成服务器资产,请将 GrpcServices
属性设置为 Server
。
<ItemGroup>
<Protobuf Include="Protos\greet.proto" GrpcServices="Server" />
</ItemGroup>
同样,该属性在客户端项目中设置为 Client
。
其他资源
本文档概述在 C# 中编写 gRPC 应用所需的概念。 此处涵盖的主题适用于基于 C-core 和基于 ASP.NET Core 的 gRPC 应用。
proto 文件
gRPC 使用协定优先方法进行 API 开发。 默认情况下,协议缓冲区 (protobuf) 用作接口定义语言 (IDL)。 .proto
文件包含:
- gRPC 服务的定义。
- 在客户端与服务器之间发送的消息。
有关 protobuf 文件的语法的详细信息,请参阅为 .NET 应用创建 Protobuf 消息。
例如,请考虑开始使用 gRPC 服务中使用的 greet.proto 文件:
- 定义
Greeter
服务。 Greeter
服务定义SayHello
调用。SayHello
发送HelloRequest
消息并接收HelloReply
消息:
syntax = "proto3";
option csharp_namespace = "GrpcGreeter";
package greet;
// The greeting service definition.
service Greeter {
// Sends a greeting
rpc SayHello (HelloRequest) returns (HelloReply);
}
// The request message containing the user's name.
message HelloRequest {
string name = 1;
}
// The response message containing the greetings.
message HelloReply {
string message = 1;
}
若要查看翻译为非英语语言的代码注释,请在 此 GitHub 讨论问题中告诉我们。
将 .proto
文件添加到 C# 应用
通过将 .proto
文件添加到 <Protobuf>
项组中,可将该文件包含在项目中:
<ItemGroup>
<Protobuf Include="Protos\greet.proto" GrpcServices="Server" />
</ItemGroup>
默认情况下,<Protobuf>
引用将生成具体的客户端和服务基类。 可使用引用元素的 GrpcServices
特性来限制 C# 资产生成。 有效 GrpcServices
选项如下:
Both
(如果不存在,则为默认值)Server
Client
None
对 .proto
文件的 C# 工具支持
需要工具包 Grpc.Tools 才能从 .proto
文件生成 C# 资产。 生成的资产(文件):
- 在每次生成项目时按需生成。
- 不会添加到项目中或是签入到源代码管理中。
- 是包含在 obj 目录中的生成工件。
服务器和客户端项目都需要此包。 Grpc.AspNetCore
元包中包含对 Grpc.Tools
的引用。 服务器项目可以使用 Visual Studio 中的包管理器或通过将 <PackageReference>
添加到项目文件来添加 Grpc.AspNetCore
:
<PackageReference Include="Grpc.AspNetCore" Version="2.28.0" />
客户端项目应直接引用 Grpc.Tools
以及使用 gRPC 客户端所需的其他包。 运行时不需要工具包,因此依赖项标记为 PrivateAssets="All"
:
<PackageReference Include="Google.Protobuf" Version="3.11.4" />
<PackageReference Include="Grpc.Net.Client" Version="2.52.0" />
<PackageReference Include="Grpc.Tools" Version="2.28.1">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
生成的 C# 资产
工具包会生成表示在所包含 .proto
文件中定义的消息的 C# 类型。
对于服务器端资产,会生成抽象服务基类型。 基类型包含 .proto
文件中所含的所有 gRPC 调用的定义。 创建一个派生自此基类型并为 gRPC 调用实现逻辑的具体服务实现。 对于 greet.proto
(前面所述的示例),会生成一个包含虚拟 SayHello
方法的抽象 GreeterBase
类型。 具体实现 GreeterService
会替代该方法,并实现处理 gRPC 调用的逻辑。
public class GreeterService : Greeter.GreeterBase
{
private readonly ILogger<GreeterService> _logger;
public GreeterService(ILogger<GreeterService> logger)
{
_logger = logger;
}
public override Task<HelloReply> SayHello(HelloRequest request, ServerCallContext context)
{
return Task.FromResult(new HelloReply
{
Message = "Hello " + request.Name
});
}
}
对于客户端资产,会生成一个具体客户端类型。 .proto
文件中的 gRPC 调用会转换为具体类型中的方法,可以进行调用。 对于 greet.proto
(前面所述的示例),会生成一个 GreeterClient
类型。 调用 GreeterClient.SayHelloAsync
以发起对服务器的 gRPC 调用。
static async Task Main(string[] args)
{
// The port number(5001) must match the port of the gRPC server.
using var channel = GrpcChannel.ForAddress("https://localhost:5001");
var client = new Greeter.GreeterClient(channel);
var reply = await client.SayHelloAsync(
new HelloRequest { Name = "GreeterClient" });
Console.WriteLine("Greeting: " + reply.Message);
Console.WriteLine("Press any key to exit...");
Console.ReadKey();
}
默认情况下,会为 <Protobuf>
项组中包含的每个 .proto
文件都生成服务器和客户端资产。 若要确保服务器项目中仅生成服务器资产,请将 GrpcServices
属性设置为 Server
。
<ItemGroup>
<Protobuf Include="Protos\greet.proto" GrpcServices="Server" />
</ItemGroup>
同样,该属性在客户端项目中设置为 Client
。