gRPC-4种通信模式
4种通信模式
1、简单模式(Simple RPC)
简单模式:也称简单 RPC,即客户端发起一次请求,服务端响应处理后返回一个结果给客户端。
在 proto 文件中可如下定义:
rpc SayHello(HelloRequest) returns (HelloResponse);
2、服务端数据流模式(Server-side streaming RPC)
服务端数据流模式:也称服务端流式 RPC,即客户端发起一次请求,服务端可以连续返回数据流。
比如:客户端向服务端发送了一个查询数据库的请求,服务端持续返回多次结果。(即客户端发送一次请求,服务端查询到数据库有一万条数据,服务端分批返回10次,每次返回1000条数据给客户端)。
在 proto 文件中可如下定义:
rpc LotsOfReplies(HelloRequest) returns (stream HelloResponse);
注意:在返回值前面加了stream
3、客户端数据流模式(Client-side streaming RPC)
客户端数据流模式:也称客户端流式 RPC,与服务端数据流模式相反,客户端持续向服务端发送数据流,在发送结束后,由服务端返回一个响应。
比如:客户端有一万条数据 ,分批多次请求服务端,服务端接收后把这些数据都存到数据库,然后返回一次结果给客户端。
在 proto 文件中可如下定义:
rpc LotsOfGreetings(stream HelloRequest) returns (HelloResponse);
注意:在参数前面加了stream
4、双向数据流模式(Bidirectional streaming RPC)
双向数据流模式:也称双向流式 RPC,即客户端和服务端都可以向对方多次收发数据。
比如:客户端有一万条数据 ,分批多次请求服务端,服务端每次接收后存到数据库后都发送一次结果给客户端。
在 proto 文件中可如下定义:
rpc BidiHello(stream HelloRequest) returns (stream HelloResponse);
注意:参数和返回前面都加了stream
代码示例
1、简单模式
product.proto
syntax = "proto3";option java_multiple_files = true;
option java_package = "com.github.xjs.grpcapi";
option java_outer_classname = "ProductProto";package product;service ProductInfo {rpc addProduct (Product) returns (ProductId);rpc getProduct(ProductId) returns(Product);
}message Product {string id = 1;string name=2;string description=3;float price=4;
}message ProductId {string value = 1;
}
客户端:
public static void main(String[] args) {ManagedChannel channel = ManagedChannelBuilder.forAddress("localhost", 50050).usePlaintext().build();ProductInfoGrpc.ProductInfoBlockingStub stub = ProductInfoGrpc.newBlockingStub(channel);Product p = Product.newBuilder().setId("1").setPrice(100).setName("21天精通Java").setDescription("21天精通Java").build();ProductId productId = stub.addProduct(p);System.out.println("productId.getValue() = " + productId.getValue());Product product = stub.getProduct(ProductId.newBuilder().setValue("99999").build());System.out.println("product.getName() = " + product.getName());channel.shutdown();
}
服务端:
public class ProductInfoImpl extends ProductInfoGrpc.ProductInfoImplBase {@Overridepublic void addProduct(Product request, StreamObserver<ProductId> responseObserver) {// System.out.println("request.toString() = " + request.toString());System.out.println(TextFormat.printer().escapingNonAscii(false).printToString(request));ProductId productId = ProductId.newBuilder().setValue(request.getId()).build();responseObserver.onNext(productId);responseObserver.onCompleted();}@Overridepublic void getProduct(ProductId request, StreamObserver<Product> responseObserver) {System.out.println(TextFormat.printer().escapingNonAscii(false).printToString(request));Product product = Product.newBuilder().setId(request.getValue()).setName("三国演义").build();responseObserver.onNext(product);responseObserver.onCompleted();}
}
2、服务端数据流模式(Server-side streaming RPC)
product.proto
syntax = "proto3";option java_multiple_files = true;
option java_package = "com.github.xjs.grpcapi.clientstream";
option java_outer_classname = "ProductProto";package product.clientstream;service ProductInfo {rpc getProductBatch (ProductGetBatchRequest) returns (stream Product);
}message ProductGetBatchRequest {int32 count = 10;}message Product {string id = 1;string name=2;string description=3;float price=4;
}
客户端:
public static void main(String[] args) throws Exception {CountDownLatch countDownLatch = new CountDownLatch(1);ManagedChannel channel = ManagedChannelBuilder.forAddress("localhost", 50050).usePlaintext().build();ProductInfoGrpc.ProductInfoStub stub = ProductInfoGrpc.newStub(channel);// 等待接收服务端的响应StreamObserver<Product> responseObserver = new StreamObserver<Product>() {@Overridepublic void onNext(Product result) {System.out.println("服务端返回:" + result.toString());}@Overridepublic void onError(Throwable throwable) {throwable.printStackTrace();}@Overridepublic void onCompleted() {System.out.println("服务端响应完成");// 关闭channelchannel.shutdown();// 结束程序countDownLatch.countDown();}};ProductGetBatchRequest request = ProductGetBatchRequest.newBuilder().setCount(10).build();stub.getProductBatch(request, responseObserver);// 等待结束countDownLatch.await();}
服务端:
@Override
public void getProductBatch(ProductGetBatchRequest request, StreamObserver<Product> responseObserver) {int count = request.getCount();for(int i=0; i<count; i++){Product product = Product.newBuilder().setId(""+(1+1)).setName("product" + i) .setPrice(100+i).build();responseObserver.onNext(product);System.out.println("发送数据:" + product);}responseObserver.onCompleted();System.out.println("发送完成");
}
3、客户端数据流模式(Client-side streaming RPC)
product.proto
syntax = "proto3";option java_multiple_files = true;
option java_package = "com.github.xjs.grpcapi.clientstream";
option java_outer_classname = "ProductProto";package product.clientstream;service ProductInfo {rpc addProductBatch (stream Product) returns (ProductAddResult);
}message Product {string id = 1;string name=2;string description=3;float price=4;
}message ProductAddResult {int32 count = 1;
}
客户端:
public static void main(String[] args) throws Exception {CountDownLatch countDownLatch = new CountDownLatch(1);ManagedChannel channel = ManagedChannelBuilder.forAddress("localhost", 50050).usePlaintext().build();ProductInfoGrpc.ProductInfoStub stub = ProductInfoGrpc.newStub(channel);// 等待接收服务端的响应StreamObserver<ProductAddResult> responseObserver = new StreamObserver<ProductAddResult>() {@Overridepublic void onNext(ProductAddResult result) {System.out.println("服务端返回:" + result.toString());}@Overridepublic void onError(Throwable throwable) {throwable.printStackTrace();}@Overridepublic void onCompleted() {System.out.println("服务端响应完成");// 关闭channelchannel.shutdown();// 结束程序countDownLatch.countDown();}};StreamObserver<Product> requestObserver = stub.addProductBatch(responseObserver);for(int i=0;i<10;i++){Product p = Product.newBuilder().setId("" + (i+1)).setPrice(100).setName("21天精通Java").setDescription("21天精通Java").build();requestObserver.onNext(p);}requestObserver.onCompleted();// 等待结束countDownLatch.await();
}
服务端:
public io.grpc.stub.StreamObserver<Product> addProductBatch(io.grpc.stub.StreamObserver<ProductAddResult> responseObserver) {return new StreamObserver<Product>() {List<Product> products = new ArrayList<>();@Overridepublic void onNext(Product product) {// 接收客户端请求System.out.println(TextFormat.printer().escapingNonAscii(false).printToString(product));products.add(product);}@Overridepublic void onError(Throwable throwable) {// 错误处理throwable.printStackTrace();}@Overridepublic void onCompleted() {// 客户端请求结束,发送响应ProductAddResult result = ProductAddResult.newBuilder().setCount(products.size()).build();responseObserver.onNext(result);responseObserver.onCompleted();System.out.println("服务端响应结束");}};
}
4、双向数据流模式(Bidirectional streaming RPC)
product.proto
syntax = "proto3";option java_multiple_files = true;
option java_package = "com.github.xjs.grpcapi.bidirectionalstream";
option java_outer_classname = "ProductProto";package product.clientstream;service ProductInfo {rpc saveProductBatch (stream Product) returns (stream ProductSaveResult);
}message ProductSaveResult {bool success = 1;
}message Product {string id = 1;string name=2;string description=3;float price=4;
}
客户端:
public static void main(String[] args) throws Exception {CountDownLatch countDownLatch = new CountDownLatch(1);ManagedChannel channel = ManagedChannelBuilder.forAddress("localhost", 50050).usePlaintext().build();ProductInfoGrpc.ProductInfoStub stub = ProductInfoGrpc.newStub(channel);// 等待接收服务端的响应StreamObserver<ProductSaveResult> responseObserver = new StreamObserver<ProductSaveResult>() {@Overridepublic void onNext(ProductSaveResult result) {System.out.println("服务端返回:" + result.toString());}@Overridepublic void onError(Throwable throwable) {throwable.printStackTrace();}@Overridepublic void onCompleted() {System.out.println("服务端响应完成");// 关闭channelchannel.shutdown();// 结束程序countDownLatch.countDown();}};StreamObserver<Product> requestObserver = stub.saveProductBatch(responseObserver);for(int i=0; i<10; i++){Product p = Product.newBuilder().setId(""+(i+1)).setName("product"+i).setPrice(100+i).build();requestObserver.onNext(p);System.out.println("客户端发送:" + p.toString());}requestObserver.onCompleted();System.out.println("客户端发送完成");// 等待结束countDownLatch.await();
}
服务端:
@Override
public StreamObserver<Product> saveProductBatch(StreamObserver<ProductSaveResult> responseObserver) {return new StreamObserver<Product>() {@Overridepublic void onNext(Product product) {System.out.println("收到客户端请求:" + product);ProductSaveResult result = ProductSaveResult.newBuilder().setSuccess(true).build();System.out.println("发送响应");responseObserver.onNext(result);}@Overridepublic void onError(Throwable throwable) {throwable.printStackTrace();}@Overridepublic void onCompleted() {System.out.println("客户端请求完成");responseObserver.onCompleted();System.out.println("服务端响应完成");}};
}
完成的源码下载:https://github.com/xjs1919/learning-demo/tree/master/grpc-demo
相关文章:
gRPC-4种通信模式
4种通信模式 1、简单模式(Simple RPC) 简单模式:也称简单 RPC,即客户端发起一次请求,服务端响应处理后返回一个结果给客户端。 在 proto 文件中可如下定义: rpc SayHello(HelloRequest) returns (Hello…...

第五项修炼—系统思考
感谢合作伙伴的推荐,圆满结束为期两天的马上消费《第五项修炼—系统思考》项目!这不仅是一次培训,更是未来实践的起点。 两天的系统思考学习让我们看到,在技术管理的每个决策背后,都蕴含着深刻的系统关联。希望各位技…...

PYNQ 框架 - VDMA驱动 - 帧缓存
目录 1. 简介 2. 代码分析 2.1 _FrameCache 类定义 2.1.1 xlnk.cma_array() 2.1.2 pointerNone 2.1.3 PynqBuffer 2.2 _FrameCache 例化与调用 2.3 _FrameCache 测试 2.4 _FrameList 类定义 2.5 _FrameList 例化与调用 2.6 _FrameList 测试 3. 帧的使用 3.1 读取帧…...
Java导出Word文档的几种方法
文章目录 1. 使用 Apache POI2. 使用 Docx4j3. 使用 JODConverter4. 使用 FreeMarker 模板 在 Java 中导出 Word 文档可以通过多种库和方法实现。以下是几种常用的方法: 1. 使用 Apache POI Apache POI 是一个强大的库,可以用来读写 Microsoft Office 格…...

OceanBase V4.3.3,首个面向实时分析场景的GA版本发布
在10月23日举办的 OceanBase年度发布会 上,我们怀着激动之情,正式向大家宣布了 OceanBase 4.3.3 GA 版的正式发布,这也是OceanBase 为实时分析(AP)场景打造的首个GA版本。 2024 年初,我们推出了 4.3.0 版本…...

Maven随笔
文章目录 1、什么是MAVEN2、Maven模型3、Maven仓库4、项目集成1_Idea集成Maven设置2_创建Maven项目3_POM配置详解4_maven 坐标详情5_Maven工程类型6_导入Maven项目 5、依赖管理1_依赖配置2_依赖传递3_可选依赖4_排除依赖4_可选依赖和排除依赖的区别5_依赖范围6_继承与聚合7_版本…...

牛客题目解析
一.最长回文子串 1.题目:给定一个仅包含小写字母的字符串,求它的最长回文子串的长度。 最长回文子串__牛客网 2.算法原理: <1>动态规划算法:O(n^2),O(n^2) 具有通性,凡涉及回文子串的问题都可利用此法解决 知识储备&am…...

AG32的3个ADC可以并联使用吗
AG32的3个ADC可以并联使用吗? Customer: 需求: 在t1时间段,用5M的速度ch1通道采样得到结果1. 在t2时间段,用5M的速度ch2通道采样得到结果2. 在t3时间段,用5M的速度ch3通道采样得到结果3. 然后如此循环 。 考虑用3…...

什么是 OpenTelemetry?
OpenTelemetry 定义 OpenTelemetry (OTel) 是一个开源可观测性框架,允许开发团队以单一、统一的格式生成、处理和传输遥测数据(telemetry data)。它由云原生计算基金会 (CNCF) 开发,旨在提供标准化协议和工具,用于收集…...

[vulnhub]DC:7
https://www.vulnhub.com/entry/dc-7,356/ 端口扫描主机发现 探测存活主机,178是靶机 nmap -sP 192.168.75.0/24 Starting Nmap 7.94SVN ( https://nmap.org ) at 2024-11-03 13:30 CST Nmap scan report for 192.168.75.1 Host is up (0.00037s l…...

个性化十足的贵族服务器,惠普ML310e Gen8,服务器中的 “潘多拉魔盒”
个性化十足的贵族服务器,惠普ML310e Gen8,服务器中的 “潘多拉魔盒” 小伙伴们大家好呀,这里是勤奋的凯尔森同学,今天给大家分享一款好玩的服务器,惠普ML310e Gen8 V2,相比大家都很熟悉HP ProLiant MicroS…...

百度社招内推
百度社招内推 「百度内推」快来投递你心仪的职位吧( 网申链接地址:https://dwz.cn/ah4OUcca),填入内推码,完成投递,get内推绿色通道~我的内推码:IZ9PVH 内推有什么好处: 简历直达…...

本地部署开源在线即时通讯软件Fiora打造个人私密聊天室
文章目录 前言1.关于Fiora2.安装Docker3.本地部署Fiora4.使用Fiora5.cpolar内网穿透工具安装6.创建远程连接公网地址7.固定Uptime Kuma公网地址 前言 相信大家在聊天时候总是很没安全感,比如在和小姐妹背着男朋友聊一些不能说的坏话,或者背着女朋友和兄…...

TS(类 接口 泛型)
文章目录 类复习相关知识属性修饰符public 修饰符属性的简写形式 protected修饰符private修饰符readonly修饰符 抽象类 接口(interface)定义类结构定义对象结构定义函数结构接口之间的继承接口自动合并 (可重复定义)一些相似的概念…...
docker 启动 neo4j
docker 启动 neo4j 1. 启动2. 导入数据 1. 启动 运行下面命令启动 neo4j, docker run \-d \--restartalways \--publish7474:7474 --publish7687:7687 \--volume$HOME/neo4j-4.4.38/data:/data \--name neo4j-apoc-4.4.38 \-e NEO4J_dbms_allow__upgradetrue \-e …...

OPENAI官方prompt文档解析
官方文档地址:https://platform.openai.com/docs/guides/gpt-best-practices 文档中文版来源:OpenAI 官方提示工程指南 [译] | 宝玉的分享 (baoyu.io) 1.写清楚说明 如果prompt给的范围十分模糊或是过于宽泛,那么GPT就会开始猜测您想要的内容,从而导致生成的结果偏离预期. …...

【GESP】C++一级练习BCQM3092,双面打印
GESP一级知识点if分支语句和取余、整除操作练习。比较简单。 题目题解详见:https://www.coderli.com/gesp-1-bcqm3092/ 【GESP】C一级练习BCQM3092,双面打印 | OneCoderGESP一级知识点if分支语句和取余、整除操作练习。比较简单。https://www.coderli.…...

mysql--多表查询
一、联合查询 作用:合并结果集就是把两个select语句的查询结果合并到一起! 合并结果集有两种方式: UNION:合并并去除重复记录,例如:SELECT * FROM t1 UNION SELECT * FROM t2; UNION ALL&a…...

RHCE-Web-nginx http实验和nginx https实验
一、web服务器简介 (1)什么是www www 是 world wide web 的缩写,也就是全球信息广播的意思。通常说的上网就是使用 www 来查询用户 所需要的信息。 www 可以结合文字、图形、影像以及声音等多媒体,并通过可以让鼠标单击超链接的…...

少儿编程学习现状洞察:青少年编程教育需求与学习频率分析
随着少儿编程教育的逐渐普及,越来越多的家庭开始关注孩子在编程学习中的表现。根据最新数据,90%的少儿编程学员保持每周至少一节课的学习频率,而95%的编程课程都安排在周末。特别是在8岁、10岁、12岁及15岁以上的年龄层次,孩子的学…...

【入坑系列】TiDB 强制索引在不同库下不生效问题
文章目录 背景SQL 优化情况线上SQL运行情况分析怀疑1:执行计划绑定问题?尝试:SHOW WARNINGS 查看警告探索 TiDB 的 USE_INDEX 写法Hint 不生效问题排查解决参考背景 项目中使用 TiDB 数据库,并对 SQL 进行优化了,添加了强制索引。 UAT 环境已经生效,但 PROD 环境强制索…...

MMaDA: Multimodal Large Diffusion Language Models
CODE : https://github.com/Gen-Verse/MMaDA Abstract 我们介绍了一种新型的多模态扩散基础模型MMaDA,它被设计用于在文本推理、多模态理解和文本到图像生成等不同领域实现卓越的性能。该方法的特点是三个关键创新:(i) MMaDA采用统一的扩散架构…...

页面渲染流程与性能优化
页面渲染流程与性能优化详解(完整版) 一、现代浏览器渲染流程(详细说明) 1. 构建DOM树 浏览器接收到HTML文档后,会逐步解析并构建DOM(Document Object Model)树。具体过程如下: (…...

高等数学(下)题型笔记(八)空间解析几何与向量代数
目录 0 前言 1 向量的点乘 1.1 基本公式 1.2 例题 2 向量的叉乘 2.1 基础知识 2.2 例题 3 空间平面方程 3.1 基础知识 3.2 例题 4 空间直线方程 4.1 基础知识 4.2 例题 5 旋转曲面及其方程 5.1 基础知识 5.2 例题 6 空间曲面的法线与切平面 6.1 基础知识 6.2…...

Java-41 深入浅出 Spring - 声明式事务的支持 事务配置 XML模式 XML+注解模式
点一下关注吧!!!非常感谢!!持续更新!!! 🚀 AI篇持续更新中!(长期更新) 目前2025年06月05日更新到: AI炼丹日志-28 - Aud…...
VTK如何让部分单位不可见
最近遇到一个需求,需要让一个vtkDataSet中的部分单元不可见,查阅了一些资料大概有以下几种方式 1.通过颜色映射表来进行,是最正规的做法 vtkNew<vtkLookupTable> lut; //值为0不显示,主要是最后一个参数,透明度…...
HTML前端开发:JavaScript 常用事件详解
作为前端开发的核心,JavaScript 事件是用户与网页交互的基础。以下是常见事件的详细说明和用法示例: 1. onclick - 点击事件 当元素被单击时触发(左键点击) button.onclick function() {alert("按钮被点击了!&…...

【开发技术】.Net使用FFmpeg视频特定帧上绘制内容
目录 一、目的 二、解决方案 2.1 什么是FFmpeg 2.2 FFmpeg主要功能 2.3 使用Xabe.FFmpeg调用FFmpeg功能 2.4 使用 FFmpeg 的 drawbox 滤镜来绘制 ROI 三、总结 一、目的 当前市场上有很多目标检测智能识别的相关算法,当前调用一个医疗行业的AI识别算法后返回…...
稳定币的深度剖析与展望
一、引言 在当今数字化浪潮席卷全球的时代,加密货币作为一种新兴的金融现象,正以前所未有的速度改变着我们对传统货币和金融体系的认知。然而,加密货币市场的高度波动性却成为了其广泛应用和普及的一大障碍。在这样的背景下,稳定…...
Python 包管理器 uv 介绍
Python 包管理器 uv 全面介绍 uv 是由 Astral(热门工具 Ruff 的开发者)推出的下一代高性能 Python 包管理器和构建工具,用 Rust 编写。它旨在解决传统工具(如 pip、virtualenv、pip-tools)的性能瓶颈,同时…...