- Reference:
- juejin.cn/course/byte…
一、RPC概念
1)本地与远程函数调用:
- 本地函数调用的流程:根据函数指针找到该函数并执行
- 远程函数调用:主要考虑三个问题
2)RPC概念模型:
- ==RPC过程的五个模型==:
- 底层细节:
3)RPC的好处与问题:
- 好处:单一职责、故障隔离
- 问题:所以需要RPC框架来解决这些问题
二、RPC的分层设计
1)层次结构:以Thrift为例
2)编解码层:
- 依赖同一份IDL文件生成代码
- 生成数据的格式:如二进制编码
- 例:TLV编码,一种二进制编码
3)协议层:
-
在编解码时,不单单要考虑元数据,还需要指定协议等其他内容,所以需要协议层
-
语法规则:以特殊结束符作为协议单元结束 / 在协议单元前规定内容长度
- 例:变长协议的构造
- 协议解析的过程:
4)网络通信层:
三、稳定性
1)保障策略:
- 熔断、限流、超时控制:
- 负载均衡、重试机制:保障请求成功率
- 长尾请求:规定响应的时间,超时重试,而不是返回false时重试
2)执行方法:
gRPC的学习:
- gRPC:
一、基本概念1)介绍gRPC:简介、对比老技术、好处2)细说HTTP协议:1.0、1.1、2.0 <扩展>3)Protocol Buffers:一种中间语言二、protobuf基本语法1)一些概念:版本设定、注释2)与Java相关的语法:一些基本配置3)基本语法:数据类型、枚举、消息三、简单gRPC开发案例1)项目模块:api、server(服务端)、client(客户端)2)①api模块:书写IDL -> 准备编译* 书写IDL:* 安装gRPC插件(一次性):帮助编译为Java并放在IDEA中* 进行编译:执行两个命令生成两个类 <过>* 优化编译:合成两个命令 + 改文件位置* 补充:细说生成的两个java类的构成3)②server(服务端)模块:4)③client(客户端)模块:* 增加repeated关键字情况:<补充>四、gRPC的四种通信方式1)四种通信方式:2)①简单RPC(一元RPC):最常见3)②服务端流式RPC:* 阻塞方式:不常见* 异步监听方式:4)③客户端流式RPC:5)④双向流式RPC:五、gRPC代理方式:<过>六、整合SpringBoot:<未完待续>1)服务端:
一、基本概念
1)介绍gRPC:简介、对比老技术、好处
- 一、简介:用的协议是HTTP2协议 -> 二进制的序列化(protobuf)
- 二、与另一个RPC框架 Thrift 的对比:<过>
- 三、gRPC的好处:原生Java语言实现
2)细说HTTP协议:1.0、1.1、2.0 <扩展>
- 一、HTTP1.0协议:
- 补充:HTTP协议底层是基于TCP协议的,而TCP协议是长连接协议,只是HTTP协议主动切断了连接(因为早期技术和硬件的问题,没有能力支持长连接,在现在不存在这种问题)
- 二、HTTP1.1协议:实现了有限的长连接 -> 有限地实现双工(本质原因是升级成webSocket的协议)
- HTTP1.x协议:(更改:图中,第一次应该是html数据,后两次是静态数据即css、js数据)
- 三、HTTP2.0协议:二进制协议、双工、长连接(stream数据流、message消息、帧frame(frame即请求头、请求体))
3)Protocol Buffers:一种中间语言
- 一、简介:
- 二、protobuf编译器的安装:
- 注意:在github下载,低版本才有适配windows
- 三、IDEA安装提示protobuf的插件:2021.2版本之后IDEA原生就支持(不用装)
二、protobuf基本语法
1)一些概念:版本设定、注释
- 写代码之前需要设定版本:2 / 3
2)与Java相关的语法:一些基本配置
- 一、多个 / 一个源文件、生成包的名字、外部类的名字
- 二、补充:了解一下逻辑包 <过>
- 三、导入:import
- 四、代码示例:IDEA
3)基本语法:数据类型、枚举、消息
- 一、先回顾一下,gRPC是用来干嘛的:
- 二、proto类型:
- 补充:“ uint ”为无符号
- 三、枚举:
- 四、消息(类似于C的结构体struct):
- 1 / 2 / 3:编号,表示在消息中的第几个字段
- 可以定义多个消息,消息可以嵌套:
- oneof:<了解>
- 五、服务:其中有服务的方法
三、简单gRPC开发案例
1)项目模块:api、server(服务端)、client(客户端)
2)①api模块:书写IDL -> 准备编译
* 书写IDL:
- 思路:写protobuf,然后编译成java
- 一、环境准备:一些1.架构上的内容
- 二、定义2.消息message(理解为一个数据结构)和3.服务service(理解为一个方法):
* 安装gRPC插件(一次性):帮助编译为Java并放在IDEA中
- 在github找到这个项目的源代码,分别导入maven的依赖、插件
* 进行编译:执行两个命令生成两个类 <过>
- 一、生成message的类:在proto文件中,打开maven:执行相应命令“ 1.compile ”
- 文件位置:target目录下
- 看看java类:
- 二、生成服务接口:“ 2.compile-custon ”
* 优化编译:合成两个命令 + 改文件位置
- 一、方法:
- 补充:怎么打开run maven -> Ctrl + Alt + R
- 二、效果:
- 三、Ps:以后run maven里面多出了我们新建的goal命令
- 四、补充:怎么删除这个新建的命令 <过>
- www.bilibili.com/video/BV13M…
- 五、如何删除生成出来的target文件夹:用maven clean命令
- 六、设置输出位置:在pom中添加两行设置(不设置的话,直接把生成的两个类剪切到相应位置即可)
* 补充:细说生成的两个java类的构成
3)②server(服务端)模块:
- 一、先要导入api模块:
- 二、在java包下,新建service包,实际上就是实现api中定义的“ hello ”服务
- 三、完成业务功能的开发:接收参数 -> 业务处理 -> 封装响应后返回
- 新建类,继承api生成接口类(大类)的xxxImplBase(内部类),重写hello方法:
- 注意:gRPC的数据返回不是通过方法的返回值,而是通过StreamObserver返回的
- 四、完成服务端的开发:
- 五、启动服务:就是run main()
4)③client(客户端)模块:
- 一、客户端模块:建个包
- 二、搭建客户端:创建通道 -> 获得代理对象 -> 封装参数 -> 拿到结果 -> 关闭通道
* 增加repeated关键字情况:<补充>
- api端:
- server端:*需要通过getXxxList()*方法拿到数据(多个)
- 补充:server端(注意一定要有这两个方法),即先将数据传出,再通知响应结束
- client端:传入多个数据
四、gRPC的四种通信方式
1)四种通信方式:
2)①简单RPC(一元RPC):最常见
【实战】:区块链项目-统一上链与认证中心:login部分
- 实际业务处理95%用到的是一元RPC
- 特点:阻塞等待
3)②服务端流式RPC:
* 阻塞方式:不常见
- 介绍:一个请求对象,多个响应结果
- 使用场景:
- 语法:加stream
- 服务端代码示例:多次响应后才onCompleted()
- 客户端:阻塞等待知道结束响应,然后再使用数据
* 异步监听方式:
- api部分与服务端部分代码不变,主要变化的是客户端部分:
- 方法:通过匿名内部类实现StreamObserver接口的三个方法,分别定义接收到消息、接收消息出现异常、接收消息结束的逻辑
- 注意:这里的builder要通过*newBuilder()*来创建
4)③客户端流式RPC:
- 概念:客户端多次发消息给服务端
- 常见场景:车上传感器不断给导航服务端发送位置消息
- 语法:
- 服务端:
- 特点:返回值是一个StreamObserver(之前两种都是void),实现这个接口的三个方法(异步的业务逻辑)
- 客户端那边,每用onNext()发送过来一条消息,服务端就会执行一次onNext()这个方法
- 客户端发送onCompleted()告诉服务端发送结束,服务端才会执行onCompleted()这个方法里的逻辑
- 客户端:用for循环模拟不定时的发送消息
- 因为要呈现客户端接收响应的数据的过程,所以还要加上awaitTermination()来阻塞客户端
5)④双向流式RPC:
- 就是:整合客户端流式和服务端流式RPC
- 常见场景:聊天室
- 语法:api模块
- 服务端:
- 客户端:
五、gRPC代理方式:<过>
- FutureStub:
六、整合SpringBoot:<未完待续>
- SpringBoot整合gRPC,主要整合的是server端和client端的api
- 而api端的方法,因为是在.probuf等非java部分完成,所有不会整合
1)服务端:
- 先导入依赖:这个依赖是github的开源项目,不是官方集成的
- 因为避免api模块引入的依赖与上面boot依赖冲突,现在api模块要重新做(不能按照之前的方式)