gRPC是由Google开发的高性能远程过程调用框架,基于HTTP/2协议传输,使用Protobuf作为接口定义和数据序列化格式,在.NET生态中有着成熟的官方支持,非常适合微服务之间的通信场景。

gRPC核心概念与优势
gRPC的核心优势在于其高效的传输性能,相比传统的REST+JSON方案,Protobuf的二进制序列化体积更小,HTTP/2的多路复用特性可以减少连接开销,在高并发场景下能显著提升服务吞吐量。在.NET中使用gRPC需要提前了解几个核心概念:
- Protobuf:即Protocol Buffers,是gRPC默认的数据序列化协议,同时用来定义服务接口和消息结构
- 服务定义:通过.proto文件声明服务包含的方法、请求和响应的消息格式
- 服务端:实现.proto文件中定义的接口逻辑,监听指定端口接收客户端请求
- 客户端:根据.proto文件生成的客户端代码,调用远程服务方法就像调用本地方法一样简单
定义Protobuf服务协议
首先我们需要创建.proto文件来定义服务和消息结构,这是gRPC开发的第一步,所有服务端和客户端代码都会基于这个文件生成。以下是一个简单的用户服务示例:
// 声明使用proto3语法
syntax = "proto3";
// 定义包名,避免命名冲突
package user;
// 指定生成的C#代码的命名空间
option csharp_namespace = "UserGrpcService";
// 定义用户查询服务的接口
service UserService {
// 根据ID查询用户的rpc方法
rpc GetUserById (GetUserByIdRequest) returns (UserResponse);
// 批量查询用户的rpc方法
rpc GetUsers (GetUsersRequest) returns (UserListResponse);
}
// 根据ID查询用户的请求消息
message GetUserByIdRequest {
int32 id = 1;
}
// 批量查询用户的请求消息
message GetUsersRequest {
repeated int32 ids = 1;
}
// 单个用户响应的消息
message UserResponse {
int32 id = 1;
string name = 2;
string email = 3;
}
// 用户列表响应的消息
message UserListResponse {
repeated UserResponse users = 1;
}
搭建.NET gRPC服务端
接下来我们创建一个ASP.NET Core项目作为gRPC服务端,首先通过NuGet安装Grpc.AspNetCore包,然后将上面的.proto文件添加到项目中,并在项目文件中配置Protobuf文件的生成规则:
<ItemGroup> <Protobuf Include="Protosuser.proto" GrpcServices="Server" /> </ItemGroup>
然后实现.proto文件中定义的服务接口,创建UserService类继承生成的基类:
using Grpc.Core;
using UserGrpcService;
namespace GrpcServer.Services
{
// 继承生成的UserService.UserServiceBase基类
public class UserService : UserService.UserServiceBase
{
private readonly ILogger<UserService> _logger;
public UserService(ILogger<UserService> logger)
{
_logger = logger;
}
// 实现GetUserById方法
public override Task<UserResponse> GetUserById(GetUserByIdRequest request, ServerCallContext context)
{
_logger.LogInformation("查询用户ID:{Id}", request.Id);
// 模拟从数据库查询用户数据
var user = new UserResponse
{
Id = request.Id,
Name = $"用户{request.Id}",
Email = $"user{request.Id}@ipipp.com"
};
return Task.FromResult(user);
}
// 实现GetUsers方法
public override Task<UserListResponse> GetUsers(GetUsersRequest request, ServerCallContext context)
{
_logger.LogInformation("批量查询用户ID:{Ids}", string.Join(",", request.Ids));
var response = new UserListResponse();
// 模拟批量查询用户数据
foreach (var id in request.Ids)
{
response.Users.Add(new UserResponse
{
Id = id,
Name = $"用户{id}",
Email = $"user{id}@ipipp.com"
});
}
return Task.FromResult(response);
}
}
}
最后在Program.cs中注册gRPC服务并启用端点映射:
var builder = WebApplication.CreateBuilder(args);
// 注册gRPC服务
builder.Services.AddGrpc();
var app = builder.Build();
// 映射UserService到对应的路由
app.MapGrpcService<UserService>();
// 添加对gRPC Web的支持,方便前端调用
app.MapGet("/", () => "gRPC服务运行中");
app.Run();
实现高性能gRPC客户端调用
客户端开发同样需要先引用.proto文件并安装Grpc.Net.Client和Google.Protobuf包,配置.proto文件的客户端生成规则:
<ItemGroup> <Protobuf Include="Protosuser.proto" GrpcServices="Client" /> </ItemGroup>
以下是控制台客户端的调用示例,包含连接池优化和超时配置,提升调用性能:
using Grpc.Net.Client;
using UserGrpcService;
namespace GrpcClient
{
class Program
{
static async Task Main(string[] args)
{
// 创建gRPC客户端通道,建议复用通道而不是每次调用都创建
using var channel = GrpcChannel.ForAddress("https://localhost:5001", new GrpcChannelOptions
{
// 设置最大接收消息大小,避免大响应报错
MaxReceiveMessageSize = 2 * 1024 * 1024,
// 设置发送消息大小限制
MaxSendMessageSize = 2 * 1024 * 1024
});
// 创建客户端实例
var client = new UserService.UserServiceClient(channel);
// 调用单个用户查询方法
try
{
var singleResponse = await client.GetUserByIdAsync(new GetUserByIdRequest { Id = 1 });
Console.WriteLine($"查询到用户:ID={singleResponse.Id},名称={singleResponse.Name},邮箱={singleResponse.Email}");
}
catch (RpcException ex)
{
Console.WriteLine($"调用失败:{ex.Status.Detail}");
}
// 调用批量查询方法
var batchResponse = await client.GetUsersAsync(new GetUsersRequest
{
Ids = { 1, 2, 3 }
});
Console.WriteLine($"批量查询到{ batchResponse.Users.Count }个用户:");
foreach (var user in batchResponse.Users)
{
Console.WriteLine($"ID={user.Id},名称={user.Name}");
}
}
}
}
性能优化建议
在实际开发中,想要实现更高性能的gRPC调用,可以参考以下优化技巧:
- 复用
GrpcChannel实例,通道的创建成本较高,建议在应用中全局复用 - 合理设置消息大小限制,避免传输过大的消息导致性能下降
- 对于高频调用场景,可以开启客户端连接池,减少连接建立的开销
- 使用Protobuf的字段编号时,尽量将常用字段放在前面,减少序列化开销
- 对于不需要返回值的场景,可以使用单向流或者设置调用超时,避免无效等待
注意:gRPC默认使用HTTP/2协议,部署时需要确保服务器支持HTTP/2,如果是跨语言调用,只需要保证双方的.proto文件定义一致即可,不需要关心具体的实现语言。
gRPC.NETProtobufgrpc_clientgrpc_server修改时间:2026-07-07 08:33:30