gRPC在.net中的使用
前言
gRPC 是一种高性能、开源的远程过程调用(RPC)框架,基于 HTTP/2 协议,支持双向流、头部压缩等特性。它默认使用 Protocol Buffers(Protobuf)作为接口定义语言(IDL)和数据序列化格式,适用于微服务、实时通信等场景。
我们可以结合常用的http服务来了解它。本质上讲,http服务是基于http协议,是一个应用层协议,RPC是基于TPC/IP,是一个传输层协议。应用层协议在传输层之上,所以RPC效率更高,所以RPC更适合内网调用,不必每次通信都要像http一样去3次握手什么的,减少了网络开销。

RPC架构
一个完整的RPC架构里面包含了四个核心的组件,分别是Client ,Server,Client Stub以及Server Stub,这个Stub大家可以理解为存根。分别说说这几个组件:
- 客户端(Client),服务的调用方。
- 服务端(Server),真正的服务提供者。
- 客户端存根,存放服务端的地址消息,再将客户端的请求参数打包成网络消息,然后通过网络远程发送给服务方。
- 服务端存根,接收客户端发送过来的消息,将消息解包,并调用本地的方法。

与http对比使用场景
1. 协议与数据格式
| 特性 | gRPC | HTTP 接口(REST) |
|---|---|---|
| 协议 | 基于 HTTP/2 | 基于 HTTP/1.1 或 HTTP/2 |
| 数据格式 | 使用 Protocol Buffers(Protobuf) | 通常使用 JSON 或 XML |
| 传输方式 | 二进制传输 | 文本传输 |
2. 性能
| 特性 | gRPC | HTTP 接口(REST) |
|---|---|---|
| 序列化效率 | Protobuf 是二进制格式,序列化效率高 | JSON/XML 是文本格式,序列化效率较低 |
| 传输效率 | 基于 HTTP/2,支持多路复用和头部压缩 | HTTP/1.1 不支持多路复用,效率较低 |
| 延迟 | 低延迟,适合实时通信 | 延迟较高,适合简单请求-响应场景 |
3. 通信模式
| 特性 | gRPC | HTTP 接口(REST) |
|---|---|---|
| 通信模式 | 支持四种模式: 1. 一元 RPC 2. 服务器流 RPC 3. 客户端流 RPC 4. 双向流 RPC |
仅支持请求-响应模式 |
| 实时通信 | 支持双向流,适合实时通信 | 不支持双向流,需通过轮询模拟 |
4. 开发与使用
| 特性 | gRPC | HTTP 接口(REST) |
|---|---|---|
| 接口定义 | 使用 Protobuf 定义服务接口,强类型 | 使用文档(如 OpenAPI)定义接口 |
| 代码生成 | 自动生成客户端和服务器代码 | 通常需要手动编写客户端代码 |
| 调试工具 | 工具较少,调试复杂 | 工具丰富(如 Postman) |
| 跨语言支持 | 支持多种语言(C++, Java, Go, C# 等) | 支持多种语言,但需要手动适配 |
5. 适用场景
| 特性 | gRPC | HTTP 接口(REST) |
|---|---|---|
| 微服务通信 | 适合高性能、低延迟的微服务通信 | 适合简单的服务间通信 |
| 实时通信 | 适合实时通信场景(如聊天、推送) | 不适合实时通信 |
| 跨语言通信 | 适合异构系统之间的通信 | 适合简单的前后端通信 |
| 浏览器支持 | 需要 gRPC-Web 适配 | 原生支持 |
一个简单的gRPCDemo
服务端
创建order.proto
syntax = "proto3"; option csharp_namespace = "GrpcService"; package order; service Order{ rpc CreateOrder(CreateRequest) returns (CreateResult); rpc QueryOrder(QueryRequest) returns (QueryResult); } //创建订单请求参数 message CreateRequest { string OrderNo = 1; string OrderName=2; double Price=3; } //创建订单返回结果 message CreateResult { bool IsSuccess = 1; // 是否成功 string Message = 2; // 错误信息 } //查询订单请求参数 message QueryRequest{ int32 Id=1; } //查询订单返回结果 message QueryResult{ int32 Id=1; string OrderNo=2; string OrderName=3; double Price=4; }
创建服务类
public class OrderService : Order.OrderBase { private readonly ILogger<OrderService> _logger; public OrderService(ILogger<OrderService> logger) { _logger = logger; } /// <summary> /// 创建订单 /// </summary> /// <param name="request"></param> /// <param name="context"></param> /// <returns></returns> public override Task<CreateResult> CreateOrder(CreateRequest request, ServerCallContext context) { //报存数据库 todo return Task.FromResult(new CreateResult { IsSuccess = true, Message = "订单创建成功" }); } /// <summary> /// 查询订单 /// </summary> /// <param name="request"></param> /// <param name="context"></param> /// <returns></returns> public override Task<QueryResult> QueryOrder(QueryRequest request, ServerCallContext context) { //查询数据库 //todo return Task.FromResult(new QueryResult { Id = request.Id, OrderNo = DateTime.Now.ToString("yyyyMMddHHmmss"), OrderName = "年货大礼包", Price = 699 }); } }
添加服务依赖并配置管道
using GrpcService.Services; var builder = WebApplication.CreateBuilder(args); // Add services to the container. builder.Services.AddGrpc(); var app = builder.Build(); // Configure the HTTP request pipeline. app.MapGrpcService<GreeterService>(); app.MapGrpcService<OrderService>(); app.MapGet("/", () => "hello world"); app.Run();
客户端
创建控制台程序
添加引用
Google.Protobuf Grpc.Net.Client Grpc.Tools
将服务端的order.proto拷贝过来,并在.csproj项目文件中添加配置项
<ItemGroup> <Protobuf Include="Protos\order.proto" GrpcServices="Client" /> </ItemGroup>
编译后自动生成代码
using Grpc.Net.Client; using GrpcService; string url = "https://localhost:7097"; using (var channel = GrpcChannel.ForAddress(url)) { var client = new Order.OrderClient(channel); var reply = await client.CreateOrderAsync(new CreateRequest { OrderName = "Order 1", OrderNo = "1", Price = 100 }); Console.WriteLine($"grpc客户端调用结果:{reply.Message},{reply.IsSuccess}"); Console.Read(); }
IOC注入的方式调用gRPC
添加注入
using GrpcClient.IOC; using static GrpcService.Order; var builder = WebApplication.CreateBuilder(args); builder.Services.AddTransient<GrpcRequestTest>(); builder.Services.AddGrpcClient<OrderClient>(o => { o.Address = new Uri("https://localhost:7097"); }).ConfigureChannel(grpcOptions => { }); var app = builder.Build(); var grpcRequestTest = app.Services.GetRequiredService<GrpcRequestTest>(); grpcRequestTest.CreateOrder(); app.Run();
public class GrpcRequestTest { private Order.OrderClient _orderClient; public GrpcRequestTest(Order.OrderClient orderClient) { _orderClient = orderClient; } public void CreateOrder() { var reply = _orderClient.CreateOrder(new CreateRequest() { OrderNo = DateTime.Now.ToString("yyyMMddHHmmss"), OrderName = "冰箱22款", Price = 1688 }); Console.WriteLine($"结果:{reply.IsSuccess},message:{reply.Message}"); Console.ReadKey(); } }
在webapi中加入gRPC服务
服务端
项目中往往需要同时提供webapi服务和gRPC服务。
创建一个webapi,添加Protos文件,注意要看下文件的生成属性。

添加OrderService.cs
在program中添加Service和配置管道。

客户端
1、拷贝proto文件
2、修改项目文件添加配置项
<ItemGroup>
<Protobuf Include="Protos\order.proto" GrpcServices="Client" />
</ItemGroup>
3、配置并调用grpc服务和webapi
using GrpcServiceWithWebApi.Client; using static GrpcServiceWithWebApi.Client.Order; var builder = WebApplication.CreateBuilder(args); //配置一个httpclient,请求地址为https://localhost:7097 builder.Services.AddHttpClient("GrpcServiceWithWebApi", c => { c.BaseAddress = new Uri("https://localhost:7095"); }); //配置一个grpcclient,请求地址为https://localhost:7097 builder.Services.AddGrpcClient<OrderClient>(o => { o.Address = new Uri("https://localhost:7095"); }).ConfigureChannel(grpcOptions => { }); var app = builder.Build(); app.MapGet("/", () => { //请求grpc服务 var client = app.Services.GetRequiredService<OrderClient>(); var reply = client.CreateOrder(new CreateRequest { OrderName = "Order 1", OrderNo = "1", Price = 100 }); var repcResult = $"grpc客户端调用结果:{reply.Message},{reply.IsSuccess}"; //请求webapi服务 var httpClient = app.Services.GetRequiredService<IHttpClientFactory>().CreateClient("GrpcServiceWithWebApi"); var response = httpClient.GetAsync("/weatherforecast").Result; var webApiResult = response.Content.ReadAsStringAsync().Result; var webApiRel = $"{repcResult} <br/> {webApiResult}"; return repcResult+webApiRel; }); app.Run();
代码地址:https://gitee.com/xiaoqingyao/g-rpcdemo.git
引用:

浙公网安备 33010602011771号