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岁以上的年龄层次,孩子的学…...

接口集成、快速对接-阿里身份证实名认证接口
身份证实名认证接口现已被应用在联网的各种业务场景中,如电商、在线教育、银行等等,下面以电商平台为例,列举翔云身份证实名认证接口在电商平台中的具体应用和优势。 电商平台的出现方便了人们的生活,进行电商的实名认证有助于提高…...

HTTP、WebSocket、gRPC 或 WebRTC:各种协议的区别
在为您的应用程序选择通信协议时,有很多不同的选择。 本文将了解四种流行的解决方案:HTTP、WebSocket、gRPC 和 WebRTC。 我们将通过深入学习其背后原理、最佳用途及其优缺点来探索每个协议。 通信方式在不断改进:变得更快、更方便、更可靠&…...

Unity3D学习FPS游戏(8)装弹和弹夹UI显示
前言:实现了武器的基本发射功能,但是我们弹夹数量是有限,之前并没有做装弹和弹夹显示的功能。本篇实现装弹和弹夹显示。 装弹和弹夹UI显示 装弹目标思路和实现 弹夹UI显示目标弹夹UI的思路和实现UI代码的思路和实现 武器控制的完整代码效果补…...

Android 托管 Github Action 发布 Github Packages ,实现 Mvn 免费自动化托管
自从多年前 JCenter 关闭服务之后,GSY 项目版本就一直发布在 Jitpack 上,如今每个月也都有大概 10w 左右下载,但是近年来时不时就会出现历史版本丢失的问题,而且有时候还不是某个具体版本丢失,而是版本里的某几个依赖突…...

火山引擎VeDI数据服务平台:在电商场景中,如何解决API编排问题?
01 平台介绍 数据服务平台可以在保证服务高可靠性和高安全性的同时,为各业务线搭建数据服务统一出口,促进数据共享,为数据和应用之间建立了一座“沟通桥梁”。 同时,解决数据理解困难、异构、重复建设、审计运维困难等问题&#x…...

【每日C/C++问题】
一、 结构体和联合体有什么区别?能否在声明过程当中缺省名字?(需要写清楚使用方法) 结构体的各个成员占用不同的内存空间,总大小是所有成员大小之和(结构体字节对齐): typedef str…...

layaair做帧动画,等待一秒之后移动坐标,坐标位置明明相同,执行的时候却会抖动。
如下图:我将1秒后面的位置与0秒的坐标位置设置为一样,然后再第二秒的时候再设置位置移动。也就是想实现这个效果,小狗先停在这里一秒,然后再开始行走。现在的问题是停在这里依然抖动一下,也就是根本就停不住。还是会变…...

SAP分包业务中能否应用后继物料?
近期物流用户在工作中遇到新的问题。在分包业务中的原材料后继(物料主数据设定非连续标识及后继物料)不成功问题。对于未知应用,需要先研究期可行性,与问题或故障不同,如果系统本身就不支持,再多分析测试也…...

【数据结构】二叉树——判断是否为完全二叉树
一、思路 有完全二叉树的解释 我们想要判断二叉树是否为完全二叉树 我们可以用队列来实现 我们先将根节点入队列 再将根节点出队列,判断取出节点是否为空、 若不为空将该节点的左右节点入队列 左右节点为空也入队列 若为空则停止入队列 然后判断队列中是否有 NUL…...

FFmpeg 4.3 音视频-多路H265监控录放C++开发十. 多线程控制帧率。循环播放,QT connect 细节,
在前面,我们总结一下前面的代码。 在 FactoryModeForAVFrameShowSDL 构造函数中 init SDL。 通过 QT timerevent机制,通过startTimer(10);每隔10ms,就会调用timerEvent事件。 在timerEvent事件中,真正的去 读取数据,…...