电脑培训班零基础网课,网站加速优化,旅游网站建设开发,毕节网站建设欢迎关注公众号#xff08;通过文章导读关注#xff1a;【11来了】#xff09;#xff0c;及时收到 AI 前沿项目工具及新技术的推送#xff01; 在我后台回复 「资料」 可领取编程高频电子书#xff01; 在我后台回复「面试」可领取硬核面试笔记#xff01; 文章导读地址… 欢迎关注公众号通过文章导读关注【11来了】及时收到 AI 前沿项目工具及新技术的推送 在我后台回复 「资料」 可领取编程高频电子书 在我后台回复「面试」可领取硬核面试笔记 文章导读地址点击查看文章导读 感谢你的关注 最新 Dubbo3 深入理解原理系列 Tripple 协议
因此 Dubbo 框架为了提升协议的通用性可以和 SpringCloud 以及其他语言应用进行通信在 Dubbo3.x 版本推出了基于 HTTP/2 的 Triple 协议也就是说 Tripple 协议在发送数据时会根据 HTTP/2 协议的格式来发送
HTTP/2 兼容 HTTP/1并且性能更好在 兼容性 和 性能 上都有所提升
Tripple 协议是 Dubbo3 推出的主力协议Tripple 的含义就是三表示是第三代Tripple 协议的特点
1、Tripple 协议是 Dubbo3 设计的基于 HTTP2 的 RPC 通信协议规范 通用性 能有所提升并且由于是基于 HTTP/2 的因此 性能 上也要比 HTTP/1.x 要好一些
2、Tripple 协议支持 流式调用
由于 Tripple 协议是基于 HTTP/2 的因此这里对 HTTP/2 协议再介绍一下
介绍一下 HTTP/2 协议
HTTP/2 协议是对 HTTP/1 协议的升级HTTP/1 的缺点就是任何一个普通的 HTTP 请求就算只发送很短的一个字符串也要带上一个请求头并且这个请求头比较大占用多个字节导致数据传输效率不高
HTTP/1 协议的请求格式如下 可以看到下边红色部分的实体也就是我们需要传输的数据
而上边都是请求头中的一些数据像一些空格、换行符都是没有必要存在的字符因此在 HTTP/2 中做了优化
HTTP/2 中所做的优化
1、HTTP/2 中 将请求和响应数据分割为更小的帧
2、并且 引入 HPACK 算法对标头压缩 减小标头大小
3、并且 支持 Stream 1、帧长度总共 24 bit表示的最大数字为 2^24bit 16M所以一个帧最大为9B头部 16M内容
2、帧类型8bit分为数据帧和控制帧
2.1、数据帧分为HEADERS 帧和 DATA 帧用来传输请求头、请求体
2.2、控制帧分为SETTINGS、PING、PRIORITY用来进行管理
3、标志位8bit可以用来表示当前帧是请求的最后一帧方便服务端解析
4、流标识符32bit表示 Stream ID最高位保留不用
5、实际传输的数据如果帧类型是 HEADERS则这里存储的就是请求头如果帧类型是 DATA则这里存储的就是请求体
HTTP/2 中的 Stream 流
HTTP/2 除了使用 HPACK 来压缩请求头的大小他还支持 Stream通过 Stream 可以极大程度上提升 HTTP/2 的并发度
在 HTTP/1 中在一个 TCP 连接上只能先发送一个请求之后必须等这个请求相应之后才可以发送第二个请求这样速度太慢了
因此在 HTTP/2 中可以在一个 TCP 连接上维护多个 Stream这样就可以并发的给服务端发送多个帧了
比如说客户端要给服务端发送 3 个请求如果只建立一个 Stream那么每次只能发送 1 个请求之后等拿到了响应结果之后再发送第 2 个请求
如果建立了三个 Stream客户端就可以使用三个线程同时将 3 个请求通过这三个 Stream 发送给服务端去
在 HTTP/2 中客户端发送请求的流程为
1、新建 TCP 连接
2、新建一个 Stream生成一个新的 StreamID生成一个控制帧帧里记录了生成的 StreamID通过 TCP 连接发送出去
3、发送请求的请求头生成要发送请求的 HEADERS 帧使用 ASCII 编码HPACK 进行压缩将压缩后的数据放到帧的 Payload 区域记录 StreamID通过 TCP 连接发送出去
4、发送请求的请求体将要发送请求的请求体中的数据按照指定的压缩算法请求中指定的压缩算法比如 gzip进行压缩使用压缩后的数据生成生成 DATA 帧记录 StreamID通过 TCP 连接发送出去
在 HTTP/2 中服务端接收请求的流程为
1、服务端从 TCP 连接中不断接受帧
2、当接收到控制帧表示客户端要和服务端建立一个 Stream服务端记录下来 StreamID在 Dubbo3 中会生成一个 ServerStreamObserver 对象
3、当接收到 HEADERS 帧取出 StreamID找到对应的 ServerStreamObserver 对象解压之后得到请求头将请求头信息存入该 ServerStreamObserver 对象中
4、当接收到 DATA 帧取出 StreamID找到对应的 ServerStreamObserver 对象将请求体解压之后按照业务逻辑处理请求体
5、处理完之后将结果生成 HEADERS 帧和 DATA 帧发送给客户端
基于 HTTP/2 的数据帧机制Tripple 协议支持 UNARY、SERVER_STREAM、BI_STREAM 三种模式
1、UNARY 最普通的服务端接受完所有请求帧之后才处理数据
2、SERVER_STREAM 服务端流式调用服务端接收完所有请求帧之后才处理数据但是可以多次发送响应 DATA 帧给客户端
3、BI_STREAM 双端流式调用客户端可以多次发送 DATA 帧服务端不断接收 DATA 帧进行处理并且将处理结果作为响应 DATA 帧多次发送给客户端客户端收到之后也会立即进行处理也就是客户端和服务端都可以不断接收 DATA 帧进行处理
接下来说一下 Tripple 协议支持的流式调用就是基于 HTTP/2 的帧实现
流式调用是在 Dubbo3.x 版本新增的如果我们需要使用流式调用的话需要自己定义对应的方法
首先引入一下需要使用的类 StreamObserver 的依赖
dependencygroupIdorg.apache.dubbo/groupIdartifactIddubbo-common/artifactIdversion3.0.7/version
/dependency并且引入一下 Tripple 协议的依赖
dependencygroupIdorg.apache.dubbo/groupIdartifactIddubbo-rpc-tripple/artifactIdversion3.0.7/version
/dependency比如说我们在 UserService 接口中定义了流式调用
public interface UserService {String hello(String name);// 服务端流式调用default void helloServerStream(String name, StreamObserverString response) {}// 双端流式调用default StreamObserverString helloStream(StreamObserverString response) {return response;}
}服务端流式调用 的话返回值需要为 void 参数中需要有 StreamObserverString
服务端对应接口实现方法为
// UserServiceImpl implements UserService
Override
public void sayHelloServerStream(String name, StreamObserverString response) {response.onNext(name hello);response.onNext(name world);response.onCompleted();
}客户端调用者代码为
userService.helloServerStream(11, new StreamObserverString(){Overridepublic void onNext(String data) {// 服务端返回的数据}Overridepublic void onError(Throwable throwable) {}Overridepublic void onCompleted(String data) {// 服务端执行完毕}
})双端流式调用 的话返回值和参数都要有 StreamObserver
服务端对应接口实现方法为
// UserServiceImpl implements UserService
Override
public StreamObserverString sayHelloStream(StreamObserverString response) {return new StreamObserverString() {Overridepublic void onNext(String data) {// 接收客户端发送的数据response.onNext(result: data);}Overridepublic void onError(Throwable throwable) {}Overridepublic void onCompleted(String data) {// 服务端执行完毕}}
}客户端调用者代码为
StreamObserverString streamObserver userService.sayHelloStream(new StreamObserverString() {Overridepublic void onNext(String data) {System.out.println(接收到响应数据 data);}Overridepublic void onError(Throwable throwable) {}Overridepublic void onCompleted(String data) {// 接收数据完毕}
})
// 客户端发送数据
streamObserver.onNext(第一次发送数据);
streamObserver.onNext(第二次发送数据);
streamObserver.onCompleted();
接下来总结一下 Tripple 协议中的流式调用的优点以及应用场景
首先流式调用的优点就是 客户端可以多次向服务端发送消息并且服务端也可以多次接收 通过 onNext 方法多次发送比如用户在处理完一部分数据之后将这一部分数据发送给服务端之后再去处理下一部分数据避免了一次发送很多数据的情况
流式调用的应用场景为接口需要发送大量数据这些数据通过一个 RPC 请求无法发送完毕需要分批发送并且需要保证发送的有序性