gRPC的通信方式-客户端流式、服务端流式、双向流式在Java的调用示例
场景
gPRC简介以及Java中使用gPRC实现客户端与服务端通信(附代码下载):
https://blog.csdn.net/BADAO_LIUMANG_QIZHI/article/details/108711541
在上面的博客中介绍了gRPC以及使用最基本的rpc通信方式即一个请求对象返回一个响应的方式进行通信。
除此之外gRPC还有以下三种方式。
服务端流式
一个请求对象,服务端返回多个结果对象
proto示例语法
rpc GetStudentsByAge(StudentRequest) returns (stream StudentResponse) {}
客户端流式
客户端传入多个请求对象,服务端返回一个响应结果。
proto示例语法
rpc GetStudentsWrapperByAges(stream StudentRequest) returns (StudentResponseList) {}
双向流式
传入多个对象可以返回多个响应对象
注:
博客:
https://blog.csdn.net/badao_liumang_qizhi
关注公众号
霸道的程序猿
获取编程相关电子书、教程推送与免费下载。
实现
服务端流式实现
在上面博客的基础上,打开Person.proto文件
message StudentRequest {int32 age = 1;
}message StudentResponse {string name = 1;int32 age = 2;string city = 3;
}
添加两个message作为请求和响应对象。
因为gRPC的请求和响应对象必须在message中定义,不能直接使用string或者int32这种作为参数。
然后在新建接口方法
service PersonService {rpc GetStudentsByAge(StudentRequest) returns (stream StudentResponse) {}
}
此方法是要请求参数为一个age,然后返回多个学生对象。
然后调用插件生成代码。
然后来到PersonServiceImpl中对接口方法进行实现
@Overridepublic void getStudentsByAge(StudentRequest request, StreamObserver<StudentResponse> responseObserver) {System.out.println("接收到的客户端消息为:"+request.getAge());responseObserver.onNext(StudentResponse.newBuilder().setName("1公众号:霸道的程序猿").setAge(30).setCity("北京").build());responseObserver.onNext(StudentResponse.newBuilder().setName("2公众号:霸道的程序猿").setAge(40).setCity("上海").build());responseObserver.onNext(StudentResponse.newBuilder().setName("3公众号:霸道的程序猿").setAge(50).setCity("广州").build());responseObserver.onCompleted();}
然后来到客户端中
ManagedChannel managedChannel = ManagedChannelBuilder.forAddress("localhost",8899).usePlaintext().build();PersonServiceGrpc.PersonServiceBlockingStub blockingStub = PersonServiceGrpc.newBlockingStub(managedChannel);System.out.println("请求-流式响应,调用getRealNameByUsername");Iterator<StudentResponse> iter = blockingStub.getStudentsByAge(StudentRequest.newBuilder().setAge(20).build());while (iter.hasNext()){StudentResponse studentResponse = iter.next();System.out.println(studentResponse.getName());System.out.println(studentResponse.getAge());System.out.println(studentResponse.getCity());}
然后运行服务端后再运行客户端
此时服务端
客户端流式实现
打开proto文件
message StudentRequest {int32 age = 1;
}message StudentResponse {string name = 1;int32 age = 2;string city = 3;
}message StudentResponseList {repeated StudentResponse studentResponse = 1;
}
添加响应的list,要实现客户端发动流式多个请求参数(年龄),服务端返回单个list对象,其中每个List的数据是学生对象。
添加接口方法
service PersonService {rpc GetStudentsWrapperByAges(stream StudentRequest) returns (StudentResponseList) {}
}
然后调用插件生成代码。打开PersonServiceImpl进行方法的实现
@Overridepublic StreamObserver<StudentRequest> getStudentsWrapperByAges(final StreamObserver<StudentResponseList> responseObserver) {return new StreamObserver<StudentRequest>() {public void onNext(StudentRequest studentRequest) {System.out.println("onNext:"+studentRequest.getAge());}public void onError(Throwable throwable) {System.out.println(throwable.getMessage());}public void onCompleted() {StudentResponse studentResponse = StudentResponse.newBuilder().setName("公众号:霸道的程序猿").setAge(20).setCity("北京").build();StudentResponse studentResponse1 = StudentResponse.newBuilder().setName("1公众号:霸道的程序猿").setAge(30).setCity("上海").build();StudentResponseList studentResponseList = StudentResponseList.newBuilder().addStudentResponse(studentResponse).addStudentResponse(studentResponse1).build();responseObserver.onNext(studentResponseList);responseObserver.onCompleted();}};}
与上面不同,客户端如果是流式请求的话,那么客户端必须使用异步的stub
PersonServiceGrpc.PersonServiceStub stub = PersonServiceGrpc.newStub(managedChannel);
客户端代码为
ManagedChannel managedChannel = ManagedChannelBuilder.forAddress("localhost",8899).usePlaintext().build();PersonServiceGrpc.PersonServiceStub stub = PersonServiceGrpc.newStub(managedChannel);System.out.println("-----------------------------");System.out.println("流式请求-响应,调用GetStudentsWrapperByAges");StreamObserver<StudentResponseList> studentResponseListStreamObserver = new StreamObserver<StudentResponseList>() {public void onNext(StudentResponseList studentResponseList) {studentResponseList.getStudentResponseList().forEach(studengResponse ->{System.out.println(studengResponse.getName());System.out.println(studengResponse.getAge());System.out.println(studengResponse.getCity());});}public void onError(Throwable throwable) {System.out.println(throwable.getMessage());}public void onCompleted() {System.out.println("completed");}};StreamObserver<StudentRequest> studentRequestStreamObserver = stub.getStudentsWrapperByAges(studentResponseListStreamObserver);studentRequestStreamObserver.onNext(StudentRequest.newBuilder().setAge(20).build());studentRequestStreamObserver.onNext(StudentRequest.newBuilder().setAge(30).build());studentRequestStreamObserver.onNext(StudentRequest.newBuilder().setAge(40).build());studentRequestStreamObserver.onCompleted();try {Thread.sleep(50000);} catch (InterruptedException e) {e.printStackTrace();}
因为是异步的所以必须使进程进行休眠才能看到效果
运行服务端后运行客户端
此时服务端
双向流式实现
打开proto文件
message StreamRequest {string request_info = 1;
}message StreamResponse {string response_info = 1;
}
新建流式请求与响应参数,然后新建接口方法
service PersonService {rpc BiTalk(stream StreamRequest) returns (stream StreamResponse) {}
}
然后实现接口方法
@Overridepublic StreamObserver<StreamRequest> biTalk(StreamObserver<StreamResponse> responseObserver) {return new StreamObserver<StreamRequest>() {@Overridepublic void onNext(StreamRequest streamRequest) {System.out.println(streamRequest.getRequestInfo());responseObserver.onNext(StreamResponse.newBuilder().setResponseInfo(UUID.randomUUID().toString()).build());}@Overridepublic void onError(Throwable throwable) {System.out.println(throwable.getMessage());}@Overridepublic void onCompleted() {responseObserver.onCompleted();}};}
在客户端中
package com.badao.grpcjava;import io.grpc.ManagedChannel;
import io.grpc.ManagedChannelBuilder;
import io.grpc.stub.StreamObserver;import java.time.LocalDate;
import java.util.Iterator;public class GrpcClient {public static void main(String[] args) {ManagedChannel managedChannel = ManagedChannelBuilder.forAddress("localhost",8899).usePlaintext().build();PersonServiceGrpc.PersonServiceStub stub = PersonServiceGrpc.newStub(managedChannel);System.out.println("-----------------------------");System.out.println("流式请求-流式响应,调用BiTalk");StreamObserver<StreamRequest> requestStreamObserver = stub.biTalk(new StreamObserver<StreamResponse>() {@Overridepublic void onNext(StreamResponse streamResponse) {System.out.println(streamResponse.getResponseInfo());}@Overridepublic void onError(Throwable throwable) {System.out.println(throwable.getMessage());}@Overridepublic void onCompleted() {System.out.println("onComplated");}});for(int i =0;i<10;i++){requestStreamObserver.onNext(StreamRequest.newBuilder().setRequestInfo(LocalDate.now().toString()).build());try {Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}}try {Thread.sleep(50000);} catch (InterruptedException e) {e.printStackTrace();}}
}
运行服务端后运行客户端
示例代码下载
https://download.csdn.net/download/BADAO_LIUMANG_QIZHI/12883063
gRPC的通信方式-客户端流式、服务端流式、双向流式在Java的调用示例相关推荐
- grpc 客户端的context 服务端获取不到_MLamp;DEV[10] | gRPC的应用
上一期和大家谈到了gRPC的快速开始,我么哪知道了gRPC是什么以及怎么快速启动,那么现在,我们来看看这个玩意具体内部是怎么运作的,这里我们同样以helloworld这个为例子来去谈.首先上期内容在这 ...
- Unity中进行网络通信:三:unity客户端和Unity服务端互相发消息
目录 一.目的 1.想知道:Unity中进行网络通信:unity客户端和Unity服务端互相发消息 二.参考 1.unity3D中使用Socket进行数据通信(三) 三.操作:一:完成:在同一个Uni ...
- 附件统一处理starter,含附件客户端和附件服务端
文章目录 附件统一处理starter,可分别作为附件客户端和附件服务端使用 一 关于项目中附件的概述 二 概要描述 三 附件starter功能划分 3.1 附件服务器,真实的存储附件 3.1.1 为前 ...
- http 缓存分为客户端缓存和服务端缓存
http 缓存分为客户端缓存和服务端缓存 1. 客户端缓存 客户端缓存指的是浏览器缓存, 浏览器缓存是最快的缓存, 因为它直接从本地获取(但有可能需要发送一个请求), 它的优势是可以减少网络流量, 加 ...
- 解决android客户端上传图片到服务端时,图片损坏的问题
解决android客户端上传图片到服务端时,图片损坏的问题 参考文章: (1)解决android客户端上传图片到服务端时,图片损坏的问题 (2)https://www.cnblogs.com/cnbl ...
- Linux Socket 两个客户端通信,服务端作为中转
Socket 两个客户端通信,服务端作为中转 Socket两个客户端通信,服务端作为中转,通过sockket的通信原理,简单的做了一个以c语言写的服务端,与自己制作的Android app 与树莓派为 ...
- C# 客户端Client与服务端Server通信
C# 客户端Client与服务端Server通信 服务端配置 服务端要先启动,等待客户端请求连接 客户端配置 客户端测试**(切记一定要先开启服务端,不然不能保证连接)**
- PhotonServer,客户端发送请求给服务端,服务端解析请求,发送回客户端响应,客户端再解析服务端发过来的响应。
1.(客户端发送给服务端)test中的构造参数并且发送 完整代码如下 test.cs using System; using System.Collections; using System.Coll ...
- oracle 客户端无法连接,Oracle客户端无法连接服务端解决方法及步骤
客户端无法连接服务端数据库,原因有网络,配置,文件访问权限,数据库服务是否已启动 等问题导致,一般排查的步骤如下: 1.检查操作系统级别网络是否通畅 ping 192.168.10.1 2.检查数据库 ...
- etcd-03 _ etcdctl:客户端操作 etcd 服务端的工具
etcd-03 _ etcdctl:客户端操作 etcd 服务端的工具 参考 [拉钩教育 etcd核心原理]
最新文章
- 设计模式学习----装饰器模式
- Java矩形区域食物链_AcWing 240. 食物链(JAVA)
- 一篇文章教会你使用html+css3制作GIF图
- C#--序列化与反序列化
- selenium 无法启动IE浏览器的解决方法
- 典型的同步客户端、服务器端套接字的创建
- python编程软件哪个好-来 看看谁最适合学Python编程
- 【转】JavaScript生成GUID的算法
- 木材材积表快速计算器_原木材积计算器
- 汉字拼音首字母检索筛选数据
- 【VBA】Str与CStr辨析
- java实验三 敏捷开发与XP实践
- 还在为英语学习发愁吗?身为程序员的你可能需要这样一份“宝典”(上)...
- 在小鸟云新春采购节买到划算的云服务器
- pandas后台导出excel_利用pandas将numpy数组导出生成excel
- 脿什么意思_襆怎么读_襆组词和拼音
- SpringCloud_JZZ_MBY
- 安卓电子市场_五款安卓工具神器
- 文本分析--NLTK自然语言处理
- html在线预览ppt excel,JavaScript实现Word、Excel、PPT在线预览
热门文章
- 马鞍山职业计算机考试,2020年职业适应性(技能)测试纲要
- PHP密码生成管理源码,php密码生成类(附源码)
- spring启动加载流程
- 13-Qt6 QMap
- 微星笔记本电脑恢复出厂或者一键还原图文流程
- top中的res只增不减_tensorflow中张量排序与accuracy计算
- 如何取消掉计算机更新图标,XP系统如何关闭右下角中的自动更新图标?
- 通讯录新建分组功能php,微信通讯录分组怎么设置
- python合并excel文件关键字_使用 Python 合并多个格式一致的 Excel 文件,Excel 表格...
- html5抬头,HTML !DOCTYPE 标签