【最新Dubbo3深入理解】Dubbo3核心Tripple协议详解

2024-02-22 16:20

本文主要是介绍【最新Dubbo3深入理解】Dubbo3核心Tripple协议详解,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

欢迎关注公众号(通过文章导读关注:【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 协议的请求格式如下:

image-20240221162128239

可以看到下边红色部分的实体也就是我们需要传输的数据

而上边都是请求头中的一些数据,像一些空格、换行符都是没有必要存在的字符,因此在 HTTP/2 中做了优化

HTTP/2 中所做的优化:

1、HTTP/2 中 将请求和响应数据分割为更小的帧

2、并且 引入 HPACK 算法对标头压缩 ,减小标头大小

3、并且 支持 Stream

image-20240221172508947

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 的依赖:

<dependency><groupId>org.apache.dubbo</groupId><artifactId>dubbo-common</artifactId><version>3.0.7</version>
</dependency>

并且引入一下 Tripple 协议的依赖

<dependency><groupId>org.apache.dubbo</groupId><artifactId>dubbo-rpc-tripple</artifactId><version>3.0.7</version>
</dependency>

比如说,我们在 UserService 接口中定义了流式调用:

public interface UserService {String hello(String name);// 服务端流式调用default void helloServerStream(String name, StreamObserver<String> response) {}// 双端流式调用default StreamObserver<String> helloStream(StreamObserver<String> response) {return response;}
}

服务端流式调用 的话,返回值需要为 void ,参数中需要有 StreamObserver<String>

服务端对应接口实现方法为:

// UserServiceImpl implements UserService
@Override
public void sayHelloServerStream(String name, StreamObserver<String> response) {response.onNext(name + " hello");response.onNext(name + " world");response.onCompleted();
}

客户端调用者代码为:

userService.helloServerStream("11", new StreamObserver<String>(){@Overridepublic void onNext(String data) {// 服务端返回的数据}@Overridepublic void onError(Throwable throwable) {}@Overridepublic void onCompleted(String data) {// 服务端执行完毕}
})

双端流式调用 的话,返回值和参数都要有 StreamObserver

服务端对应接口实现方法为:

// UserServiceImpl implements UserService
@Override
public StreamObserver<String> sayHelloStream(StreamObserver<String> response) {return new StreamObserver<String>() {@Overridepublic void onNext(String data) {// 接收客户端发送的数据response.onNext("result:" + data);}@Overridepublic void onError(Throwable throwable) {}@Overridepublic void onCompleted(String data) {// 服务端执行完毕}}
}

客户端调用者代码为:

StreamObserver<String> streamObserver = userService.sayHelloStream(new StreamObserver<String>() {@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 请求无法发送完毕,需要分批发送,并且需要保证发送的有序性

这篇关于【最新Dubbo3深入理解】Dubbo3核心Tripple协议详解的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/735807

相关文章

Java中的Cursor使用详解

《Java中的Cursor使用详解》本文介绍了Java中的Cursor接口及其在大数据集处理中的优势,包括逐行读取、分页处理、流控制、动态改变查询、并发控制和减少网络流量等,感兴趣的朋友一起看看吧... 最近看代码,有一段代码涉及到Cursor,感觉写法挺有意思的。注意是Cursor,而不是Consumer

SpringBoot项目注入 traceId 追踪整个请求的日志链路(过程详解)

《SpringBoot项目注入traceId追踪整个请求的日志链路(过程详解)》本文介绍了如何在单体SpringBoot项目中通过手动实现过滤器或拦截器来注入traceId,以追踪整个请求的日志链... SpringBoot项目注入 traceId 来追踪整个请求的日志链路,有了 traceId, 我们在排

HTML5中下拉框<select>标签的属性和样式详解

《HTML5中下拉框<select>标签的属性和样式详解》在HTML5中,下拉框(select标签)作为表单的重要组成部分,为用户提供了一个从预定义选项中选择值的方式,本文将深入探讨select标签的... 在html5中,下拉框(<select>标签)作为表单的重要组成部分,为用户提供了一个从预定义选项中

Python中多线程和多进程的基本用法详解

《Python中多线程和多进程的基本用法详解》这篇文章介绍了Python中多线程和多进程的相关知识,包括并发编程的优势,多线程和多进程的概念、适用场景、示例代码,线程池和进程池的使用,以及如何选择合适... 目录引言一、并发编程的主要优势二、python的多线程(Threading)1. 什么是多线程?2.

Python爬虫selenium验证之中文识别点选+图片验证码案例(最新推荐)

《Python爬虫selenium验证之中文识别点选+图片验证码案例(最新推荐)》本文介绍了如何使用Python和Selenium结合ddddocr库实现图片验证码的识别和点击功能,感兴趣的朋友一起看... 目录1.获取图片2.目标识别3.背景坐标识别3.1 ddddocr3.2 打码平台4.坐标点击5.图

Java 8 Stream filter流式过滤器详解

《Java8Streamfilter流式过滤器详解》本文介绍了Java8的StreamAPI中的filter方法,展示了如何使用lambda表达式根据条件过滤流式数据,通过实际代码示例,展示了f... 目录引言 一.Java 8 Stream 的过滤器(filter)二.Java 8 的 filter、fi

Java中实现订单超时自动取消功能(最新推荐)

《Java中实现订单超时自动取消功能(最新推荐)》本文介绍了Java中实现订单超时自动取消功能的几种方法,包括定时任务、JDK延迟队列、Redis过期监听、Redisson分布式延迟队列、Rocket... 目录1、定时任务2、JDK延迟队列 DelayQueue(1)定义实现Delayed接口的实体类 (

Rust中的BoxT之堆上的数据与递归类型详解

《Rust中的BoxT之堆上的数据与递归类型详解》本文介绍了Rust中的BoxT类型,包括其在堆与栈之间的内存分配,性能优势,以及如何利用BoxT来实现递归类型和处理大小未知类型,通过BoxT,Rus... 目录1. Box<T> 的基础知识1.1 堆与栈的分工1.2 性能优势2.1 递归类型的问题2.2

springboot的调度服务与异步服务使用详解

《springboot的调度服务与异步服务使用详解》本文主要介绍了Java的ScheduledExecutorService接口和SpringBoot中如何使用调度线程池,包括核心参数、创建方式、自定... 目录1.调度服务1.1.JDK之ScheduledExecutorService1.2.spring

MySQL 中的服务器配置和状态详解(MySQL Server Configuration and Status)

《MySQL中的服务器配置和状态详解(MySQLServerConfigurationandStatus)》MySQL服务器配置和状态设置包括服务器选项、系统变量和状态变量三个方面,可以通过... 目录mysql 之服务器配置和状态1 MySQL 架构和性能优化1.1 服务器配置和状态1.1.1 服务器选项