目录

一、gRPC 基础:为什么它适合微服务?

二、gRPC 的四种通信模式及.NET Core 实现

1. 一元 RPC(Unary RPC):最基础的请求 - 响应模式

2. 服务器流式 RPC(Server Streaming RPC):服务端批量推送数据

3. 客户端流式 RPC(Client Streaming RPC):客户端批量提交数据

4. 双向流式 RPC(Bidirectional Streaming RPC):实时双向交互

三、gRPC 在微服务中的核心使用场景

四、gRPC vs RESTful API:优劣势对比

五、总结:如何在微服务中选择?


在微服务架构中,服务间通信的效率、可靠性和灵活性直接影响系统整体性能。gRPC 作为一种高性能的远程过程调用(RPC)框架,基于 HTTP/2 协议和 Protocol Buffers(Protobuf)序列化机制,已成为.NET Core 微服务间通信的热门选择。本文将详细解析 gRPC 的四种通信模式、适用场景,并与 RESTful API 进行对比,帮助你在微服务架构中合理选型。

一、gRPC 基础:为什么它适合微服务?

gRPC 是由 Google 开发的开源 RPC 框架,其核心优势源于两大技术基石:

  • HTTP/2 协议:支持多路复用、二进制帧传输、服务器推送等特性,解决了 HTTP/1.1 的连接阻塞问题。
  • Protocol Buffers:一种强类型二进制序列化格式,相比 JSON/XML,序列化后体积更小、解析速度更快,且自带接口定义能力。

在.NET Core 中,gRPC 通过Grpc.AspNetCore包提供原生支持,可与ASP.NET Core 生态无缝集成,尤其适合微服务间的高频、低延迟通信场景。

二、gRPC 的四种通信模式及.NET Core 实现

gRPC 基于 “服务定义” 和 “消息类型” 构建通信契约,通过.proto文件定义接口,再生成客户端和服务端代码。其四种通信模式覆盖了几乎所有微服务交互场景:

1. 一元 RPC(Unary RPC):最基础的请求 - 响应模式

定义:客户端发送一个请求,服务端返回一个响应,类似传统的 HTTP 接口调用。

流程

  1. 客户端调用生成的方法,发送请求消息。
  2. 服务端接收请求并处理。
  3. 服务端返回响应消息,一次交互结束。

代码示例

  • .proto文件定义:
syntax = "proto3";
service UserService {// 一元RPC:根据ID查询用户rpc GetUserById (UserIdRequest) returns (UserResponse);
}message UserIdRequest {int32 user_id = 1;
}message UserResponse {int32 id = 1;string name = 2;string email = 3;
}
  • 服务端实现(.NET Core):
public class UserService : UserService.UserServiceBase
{public override Task<UserResponse> GetUserById(UserIdRequest request, ServerCallContext context){// 模拟查询数据库var user = new UserResponse { Id = request.UserId, Name = "张三", Email = "zhangsan@example.com" };return Task.FromResult(user);}
}
  • 客户端调用:
var channel = GrpcChannel.ForAddress("https://localhost:5001");​
var client = new UserService.UserServiceClient(channel);​
var response = await client.GetUserByIdAsync(new UserIdRequest { UserId = 1 });​
Console.WriteLine($"用户名称:{response.Name}");

适用场景:简单的查询或命令操作,如 “根据 ID 查询资源”“提交表单数据” 等单次交互场景。

2. 服务器流式 RPC(Server Streaming RPC):服务端批量推送数据

定义:客户端发送一个请求,服务端返回一个持续的数据流(多个响应),直到服务端主动结束流。

流程

  1. 客户端发送请求。
  2. 服务端接收后,通过流多次返回响应(如分页数据、实时日志)。
  3. 服务端关闭流,客户端接收完成。

代码示例

  • .proto文件定义:
service OrderService {// 服务器流式RPC:获取订单历史(分页推送)rpc GetOrderHistory (OrderHistoryRequest) returns (stream OrderResponse);
}message OrderHistoryRequest {int32 user_id = 1;
}message OrderResponse {int32 order_id = 1;string product = 2;double amount = 3;
}
  • 服务端实现:
public class OrderService : OrderService.OrderServiceBase
{public override async Task GetOrderHistory(OrderHistoryRequest request, IServerStreamWriter<OrderResponse> responseStream, ServerCallContext context){// 模拟分批返回数据var orders = new List<OrderResponse>{new() { OrderId = 1, Product = "手机", Amount = 5999 },new() { OrderId = 2, Product = "电脑", Amount = 8999 },new() { OrderId = 3, Product = "耳机", Amount = 999 }};foreach (var order in orders){await responseStream.WriteAsync(order);await Task.Delay(500); // 模拟延迟}}
}
  • 客户端调用:
var client = new OrderService.OrderServiceClient(channel);
using var call = client.GetOrderHistory(new OrderHistoryRequest { UserId = 1 });
await foreach (var order in call.ResponseStream.ReadAllAsync())
{Console.WriteLine($"订单ID:{order.OrderId},商品:{order.Product}");
}

适用场景:需要服务端持续返回数据的场景,如 “分页查询大量数据”“实时日志推送”“股票价格更新” 等。

3. 客户端流式 RPC(Client Streaming RPC):客户端批量提交数据

定义:客户端通过流多次发送请求,服务端在接收完所有请求后返回一个响应。

流程

  1. 客户端通过流多次发送数据(如分批上传文件)。
  2. 服务端接收所有数据后处理。
  3. 服务端返回一个最终响应。

代码示例

  • .proto文件定义:
service FileService {// 客户端流式RPC:上传文件(分片)rpc UploadFile (stream FileChunkRequest) returns (FileUploadResponse);
}message FileChunkRequest {bytes chunk_data = 1;string file_name = 2;bool is_last_chunk = 3;
}message FileUploadResponse {bool success = 1;string file_path = 2;
}
  • 服务端实现:
public class FileService : FileService.FileServiceBase
{public override async Task<FileUploadResponse> UploadFile(IAsyncStreamReader<FileChunkRequest> requestStream, ServerCallContext context){var filePath = Path.Combine("uploads", Guid.NewGuid().ToString());using var fs = new FileStream(filePath, FileMode.Create);while (await requestStream.MoveNextAsync()){var chunk = requestStream.Current;await fs.WriteAsync(chunk.ChunkData.ToArray());if (chunk.IsLastChunk) break;}return new FileUploadResponse { Success = true, FilePath = filePath };}
}
  • 客户端调用:
var client = new FileService.FileServiceClient(channel);
using var call = client.UploadFile();// 模拟分片上传
var chunks = new List<FileChunkRequest>
{new() { ChunkData = ByteString.CopyFromUtf8("第一部分数据"), FileName = "test.txt", IsLastChunk = false },new() { ChunkData = ByteString.CopyFromUtf8("第二部分数据"), FileName = "test.txt", IsLastChunk = true }
};foreach (var chunk in chunks)
{await call.RequestStream.WriteAsync(chunk);
}
await call.RequestStream.CompleteAsync();var response = await call.ResponseAsync;
Console.WriteLine($"上传结果:{response.Success},路径:{response.FilePath}");

适用场景:客户端需要批量提交数据的场景,如 “大文件分片上传”“批量数据导入”“传感器批量上报数据” 等。

4. 双向流式 RPC(Bidirectional Streaming RPC):实时双向交互

定义:客户端和服务端通过各自的流双向发送数据,双方可独立发送 / 接收,无需等待对方响应,类似 “即时通讯”。

流程

  1. 客户端和服务端建立流连接。
  2. 客户端可随时发送数据,服务端也可随时返回数据。
  3. 任意一方关闭流,交互结束。

代码示例

  • .proto文件定义:
service ChatService {// 双向流式RPC:实时聊天rpc Chat (stream ChatMessageRequest) returns (stream ChatMessageResponse);
}message ChatMessageRequest {string user = 1;string message = 2;
}message ChatMessageResponse {string timestamp = 1;string user = 2;string message = 3;
}
  • 服务端实现:
public class ChatService : ChatService.ChatServiceBase
{public override async Task Chat(IAsyncStreamReader<ChatMessageRequest> requestStream, IServerStreamWriter<ChatMessageResponse> responseStream, ServerCallContext context){// 并行处理:一边读客户端消息,一边写响应var readTask = Task.Run(async () =>{while (await requestStream.MoveNextAsync()){var request = requestStream.Current;// 广播消息(简化处理,实际需维护连接池)await responseStream.WriteAsync(new ChatMessageResponse{Timestamp = DateTime.Now.ToString("HH:mm:ss"),User = request.User,Message = request.Message});}});await readTask;}
}
  • 客户端调用:
var client = new ChatService.ChatServiceClient(channel);
using var call = client.Chat();// 发送消息的任务
var sendTask = Task.Run(async () =>
{while (true){Console.Write("输入消息(退出请输入q):");var msg = Console.ReadLine();if (msg == "q") break;await call.RequestStream.WriteAsync(new ChatMessageRequest{User = "客户端A",Message = msg});}await call.RequestStream.CompleteAsync();
});// 接收消息的任务
var receiveTask = Task.Run(async () =>
{await foreach (var response in call.ResponseStream.ReadAllAsync()){Console.WriteLine($"[{response.Timestamp}] {response.User}:{response.Message}");}
});await Task.WhenAll(sendTask, receiveTask);

适用场景:需要实时双向交互的场景,如 “即时通讯”“多人协作编辑”“实时游戏对战” 等。

三、gRPC 在微服务中的核心使用场景

结合上述四种模式,gRPC 在微服务中的典型应用场景包括:

  1. 高频内部服务调用:微服务间的同步通信(如订单服务调用支付服务),利用 gRPC 的高性能降低延迟。
  2. 实时数据推送:如物流系统的位置实时更新(服务器流式)、监控系统的指标实时上报(客户端流式)。
  3. 大数据传输:通过流式传输避免单次请求数据量过大导致的超时(如数据备份、日志同步)。
  4. 双向实时交互:如客服系统的实时对话、协作工具的实时状态同步。

四、gRPC vs RESTful API:优劣势对比

维度

gRPC

RESTful API

性能

极高:HTTP/2 多路复用 + 二进制协议,吞吐量是 REST 的 5-10 倍。

中等:HTTP/1.1 文本协议(JSON/XML),解析耗时。

契约定义

强类型:通过.proto文件严格定义接口,支持自动生成代码,编译期校验。

弱类型:依赖文档(如 Swagger),需手动保证客户端与服务端一致。

通信模式

支持四种模式(一元、服务端流、客户端流、双向流),灵活应对复杂场景。

仅支持请求 - 响应模式(扩展需 WebSocket 等)。

兼容性

较差:二进制协议不适合浏览器直接调用,需通过网关转换。

极好:基于 HTTP/1.1 文本协议,浏览器、Postman 等工具直接支持。

学习成本

较高:需学习 Protobuf 语法、gRPC 概念及工具链。

较低:基于 HTTP 标准,开发者熟悉度高。

生态工具

正在完善:.NET Core 集成良好,但调试工具(如浏览器 DevTools)支持有限。

成熟:Swagger、Postman 等工具生态丰富。

适用场景

微服务内部通信、实时交互、高性能需求场景。

面向用户的 API(BFF 层)、简单的跨系统交互。

五、总结:如何在微服务中选择?

gRPC 凭借高性能灵活的流式通信,成为.NET Core 微服务内部通信的首选方案,尤其适合需要实时性、高吞吐量的场景。但如果你的服务需要直接暴露给浏览器或第三方(非微服务场景),RESTful API 仍是更稳妥的选择。

在实际架构中,可采用 “内外分离” 策略:内部微服务用 gRPC 提升效率,外部通过 BFF 层(Backend For Frontend)将 gRPC 转换为 RESTful API 供前端调用,兼顾性能与兼容性。

希望本文能帮助你快速掌握 gRPC 在.NET Core 微服务中的应用,不妨从一个简单的一元 RPC 接口开始尝试,逐步扩展到流式场景,体验其带来的性能提升!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/bicheng/90219.shtml
繁体地址,请注明出处:http://hk.pswp.cn/bicheng/90219.shtml
英文地址,请注明出处:http://en.pswp.cn/bicheng/90219.shtml

如若内容造成侵权/违法违规/事实不符,请联系英文站点网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

HTML零基础快速入门教程(详细篇)

本文详细介绍HTML零基础快速入门的基础知识&#xff0c;包括HTML的介绍、语言的一些实际作用、语法规范注意&#xff0c;如标签结构、标签属性、大小写不敏感等&#xff0c;还介绍了HTML文件的具体书写规则&#xff0c;如文件扩展名、文档类型声明和HTML结构以及具体的一些HTML…

LLM评测框架Ragas:SQL指标(解决了Ollama推理框架不支持的问题)

SQL类的度量指标是指运行SQL后的结果和预期之间的一个度量值。 datacompy score datacompy score 使用DataCompy(一个比较pandas的数据格式的python类,所以需要按照datacompy:pip install datacompy),默认是按照rows比较,也可以设置按照columns比较,这个事通过mode参数…

ubuntu24 ros2 jazzy

安装2 software & update 选择其它 安装 一、前提准备 检查操作系统版本&#xff1a; 确保你的系统版本是Ubuntu 24.04。你可以通过运行lsb_release -a命令来检查当前的系统版本。 设置UTF-8支持&#xff1a; ROS 2需要UTF-8编码支持。你可以通过以下命令来检查和设置UTF…

设备虚拟化技术

设备虚拟化技术概述设备虚拟化技术通过软件模拟物理硬件设备&#xff0c;使多个操作系统或应用程序能够共享同一台物理设备。它广泛应用于云计算、服务器整合和测试环境等领域。核心目标是提高资源利用率、隔离性和灵活性。•当接入的用户数增加到原交换机端口密度不能满足接入…

开发避坑短篇(3):解决@vitejs plugin-vue@5.0.5对Vite^5.0.0的依赖冲突

异常信息 # npm resolution error reportWhile resolving:system3.8.8 Found: vite6.2.3 node_modules/vitedev vite"6.2.3" from the root projectCould not resolve dependency: peer vite"^5.0.0" from vitejs/plugin-vue5.0.5 node_modules/vitejs/plu…

k8s快速部署(亲测无坑)

文章目录k8s快速部署&#xff08;亲测无坑&#xff09;一、网络划分二、CentOS7设置 标题固定IP和阿里云YUM源三、主机环境配置四、虚拟机的拷贝五、安装docker(每台主机都需要安装)六、安装kubelet,kubeadm,kubectl(每台机器都需要执行)遇到的问题参考文档k8s快速部署&#xf…

简易RAG问答引擎的构建与体验

RAG&#xff08;检索增强生成&#xff09;是结合检索与生成式 AI 的技术框架。核心逻辑是先从外部知识库精准检索相关信息&#xff0c;再将其作为上下文输入大模型生成回答。技术上依赖检索引擎&#xff08;如向量数据库、BM25&#xff09;、大语言模型&#xff08;如 GPT、LLa…

C++11特性学习 Day1

nullptr对于c中null (void*)0&#xff0c;所以在为函数传参传入0时&#xff0c;无法清楚地分辨是int类型的0还是指的是空指针null在C11中清晰的将空指针变为了nullptr&#xff0c;0专指int型的数字0override关键字在子类中对父类的函数的覆写之后加上override关键字&#xff0…

微算法科技(NASDAQ: MLGO)探索优化量子纠错算法,提升量子算法准确性

随着量子计算技术的飞速发展&#xff0c;量子计算机在解决复杂计算问题上的潜力日益显现。然而&#xff0c;量子计算面临的一个重大挑战是量子比特的脆弱性&#xff0c;即量子比特容易受到环境噪声和干扰的影响&#xff0c;导致量子态的塌缩和计算结果的错误。微算法科技&#…

MongoDB数据库详解-针对大型分布式项目采用的原因以及基础原理和发展-卓伊凡|贝贝|莉莉

MongoDB数据库详解-针对大型分布式项目采用的原因以及基础原理和发展-卓伊凡|贝贝|莉莉由于老产品即时通讯私有化软件就是采用MongoDB &#xff0c;但是版本实在太低&#xff0c;要做大更新&#xff0c;其次针对10年前完美运营的项目来到10年后的现在就不一定行&#xff0c;优雅…

Kotlin 中的单例模式(Singleton)与对象声明

在 Kotlin 中&#xff0c;类描述的是一种通用结构&#xff0c;可以多次实例化&#xff0c;也可以用多种方式实例化。但有时我们只需要单个实例&#xff0c;不多不少。单例模式能帮你更好地组织代码&#xff0c;把相关的方法聚合在一起。 单例模式是什么&#xff1f; 单例模式是…

Shell 编程基础入门从认识到实战

对于刚接触 Linux 或 Unix 系统的开发者来说&#xff0c;Shell 脚本往往是自动化操作的第一道门槛。它不像 Python 那样语法简洁&#xff0c;也不像 Java 那样有完善的面向对象体系&#xff0c;但却能以极少的代码实现强大的系统管理功能。本文将从 Shell 的基本概念讲起&#…

混合遗传粒子群算法在光伏系统MPPT中的应用研究

混合遗传粒子群算法在光伏系统MPPT中的应用研究 前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家&#xff0c;觉得好请收藏。点击跳转到网站。 摘要 本文针对光伏系统最大功率点跟踪(MPPT)问题&#xff0…

机器视觉的布料丝印应用

在纺织印染行业&#xff0c;布料丝印工艺的精度直接决定产品外观质量与市场竞争力。传统丝印设备依赖机械定位与人工校准&#xff0c;面对高密度图案、柔性面料或复杂纹理时&#xff0c;易出现套色偏移、油墨渗透不均等问题&#xff0c;导致良品率波动与生产成本攀升。 随着机…

前端常用类库

常用类库 类库作用 类库可以帮助我们快速实现项目业务的开发与功能的实现, 帮助我们解放劳动力提高生产效率, 前端中的类库与框架都是由原生javascript编写, 提供给其他开发者应用于某一业务环境或者需求。一般有开发者/团队开源维护. 优秀的类库需要具备高度封装可用, 稳定, …

通俗易懂循环神经网络(RNN)指南

本文用直观类比、图表和代码&#xff0c;带你轻松理解RNN及其变体&#xff08;LSTM、GRU、双向RNN&#xff09;的原理和应用。什么是循环神经网络 循环神经网络&#xff08;Recurrent Neural Network, RNN&#xff09;是一类专门用于处理序列数据的神经网络。与前馈神经网络不同…

【SVM】支持向量机实例合集

基于Java的SVM(支持向量机)实例合集 以下是一个基于Java的SVM(支持向量机)实例合集,包含核心代码示例和应用场景说明。这些例子基于流行的机器学习库(如LIBSVM、Weka、JSAT)实现。 数据准备与加载 使用LIBSVM格式加载数据集: // 加载LIBSVM格式数据 svm_problem pr…

Python100个库分享第38个—lxml(爬虫篇)

目录专栏导读&#x1f4da; 库简介&#x1f3af; 主要特点&#x1f6e0;️ 安装方法Windows安装Linux/macOS安装验证安装&#x1f680; 快速入门基本使用流程HTML vs XML解析&#x1f50d; 核心功能详解1. XPath选择器2. CSS选择器支持3. 元素操作&#x1f577;️ 实战爬虫案例…

imx6ull-系统移植篇17——linux顶层 Makefile(上)

目录 前言 顶层 Makefile 源码简析 版本号 MAKEFLAGS 变量 命令输出 静默输出 设置编译结果输出目录 代码检查 模块编译 设置目标架构和交叉编译器 调用 scripts/Kbuild.include 文件 交叉编译工具变量设置 头文件路径变量 导出变量 make xxx_defconfig 过程 …

OpenCV 官翻6 - Computational Photography

文章目录图像去噪目标理论OpenCV中的图像去噪1、cv.fastNlMeansDenoisingColored()2、cv.fastNlMeansDenoisingMulti()附加资源图像修复目标基础概念代码补充资源练习高动态范围成像&#xff08;HDR&#xff09;目标理论基础曝光序列HDR1、将曝光图像加载到列表中2、将曝光序列…