java 版 gRPC 实战之五:双向流
欢迎访问我的 GitHub
这里分类和汇总了欣宸的全部原创(含配套源码):https://github.com/zq2599/blog_demos
本篇概览
本文是《java 版 gRPC 实战》系列的第五篇,目标是掌握双向流类型的服务,即请求参数是流的形式,响应的内容也是流的形式;
先来看看官方资料对双向流式 RPC 的介绍:是双方使用读写流去发送一个消息序列。两个流独立操作,因此客户端和服务器 可以以任意喜欢的顺序读写:比如, 服务器可以在写入响应前等待接收所有的客户端消息,或者可以交替 的读取和写入消息,或者其他读写的组合。 每个流中的消息顺序被预留;
掌握了客户端流和服务端流两种类型的开发后,双向流类型就很好理解了,就是之前两种类型的结合体,请求和响应都按照流的方式处理即可;
今天的实战,咱们来设计一个在线商城的功能:批量减扣库存,即客户端提交多个商品和数量,服务端返回每个商品减扣库存成功和失败的情况;
咱们尽快进入编码环节吧,具体内容如下:
在 proto 文件中定义双向流类型的 gRPC 接口,再通过 proto 生成 java 代码
开发服务端应用
开发客户端应用
验证
源码下载
本篇实战中的完整源码可在 GitHub 下载到,地址和链接信息如下表所示(https://github.com/zq2599/blog_demos):
这个 git 项目中有多个文件夹,《java 版 gRPC 实战》系列的源码在 grpc-tutorials 文件夹下,如下图红框所示:
grpc-tutorials 文件夹下有多个目录,本篇文章对应的服务端代码在 double-stream-server-side 目录下,客户端代码在 double-stream-client-side 目录下,如下图:
在 proto 文件中定义双向流类型的 gRPC 接口
首先要做的就是定义 gRPC 接口,打开 mall.proto,在里面新增方法和相关的数据结构,需要重点关注的是 BatchDeduct 方法的入参 ProductOrder 和返回值 DeductReply 都添加了 stream 修饰(ProductOrder 是上一章定义的),代表该方法是双向流类型:
双击下图红框中的 task 即可生成 java 代码:
生成下图红框中的文件,即服务端定义和返回值数据结构:
接下来开发服务端;
开发服务端应用
在父工程 grpc-turtorials 下面新建名为 double-stream-server-side 的模块,其 build.gradle 内容如下:
配置文件 application.yml:
启动类 DoubleStreamServerSideApplication.java 的代码就不贴了,普通的 springboot 启动类而已;
重点是提供 grpc 服务的 GrpcServerService.java,咱们要做的就是给上层框架返回一个匿名类,至于里面的 onNext、onCompleted 方法何时被调用是上层框架决定的,另外还准备了成员变量 totalCount,这样就可以记录总数了,由于请求参数是流,因此匿名类的 onNext 会被多次调用,并且由于返回值是流,因此 onNext 中调用了 responseObserver.onNext 方法来响应流中的每个请求,这样客户端就不断收到服务端的响应数据(即客户端的 onNext 方法会被多次调用):
开发客户端应用
在父工程 grpc-turtorials 下面新建名为 double-stream-server-side 的模块,其 build.gradle 内容如下:
配置文件 application.yml,设置自己的 web 端口号和服务端地址:
启动类 DoubleStreamClientSideApplication.java 的代码就不贴了,普通的 springboot 启动类而已;
正常情况下我们都是用 StreamObserver 处理服务端响应,这里由于是异步响应,需要额外的方法从 StreamObserver 中取出业务数据,于是定一个新接口,继承自 StreamObserver,新增 getExtra 方法可以返回 String 对象,详细的用法稍后会看到:
重头戏来了,看看如何远程调用双向流类型的 gRPC 接口,代码中已经添加详细注释:
最后做个 web 接口,可以通过 web 请求验证远程调用:
编码完成,开始验证;
验证
启动服务端 DoubleStreamServerSideApplication:
启动客户端 DoubleStreamClientSideApplication:
这里要改:浏览器输入 http://localhost:8083/?count=10,响应如下,可见远程调用 gRPC 服务成功,流式响应的每一笔返回都被客户端收到:
下面是服务端日志,可见逐一处理了客户端的每一笔数据:
下面是客户端日志,可见由于 CountDownLatch 的作用,发起 gRPC 请求的线程一直等待 responseObserver.onCompleted 在另一个线程被执行完后,才会继续执行:
至此,四种类型的 gRPC 服务及其客户端开发就完成了,一般的业务场景咱们都能应付自如,接下来的文章咱们会继续深入学习,了解复杂场景下的 gRPC 操作;
欢迎关注 InfoQ:程序员欣宸
版权声明: 本文为 InfoQ 作者【程序员欣宸】的原创文章。
原文链接:【http://xie.infoq.cn/article/65b4b93a3601002effb8eea40】。文章转载请联系作者。
评论