RocketMQ 5.0:无状态代理模式的探索与实践

news/2024/4/29 13:12:07/文章来源:https://blog.csdn.net/alisystemsoftware/article/details/127248969

在这里插入图片描述

本文作者:金吉祥, Apache RocketMQ PMC Member,阿里云智能高级技术专家

背景

在这里插入图片描述

首先,让我们来看下是遇到了哪些痛点问题,促使我们去探索一种无状态代理的RocketMQ新架构的;

RocketMQ 拥有一套极简的架构,多语言客户端通过自定义的 Remoting 协议与后端 NameServer 和 Broker建立 TCP 长连接,然后进行消息的路由发现以及完整的消息收发。这套架构的优势是:架构极简,客户端 与 Broker 通过 TCP 直连的模式,拥有较高的性能以及较低的延迟。同时,这套架构采取的是队列模型,非常适合基于队列批量高速拉取消息的场景。

同时,RocketMQ 在上云过程中面临了各种各样的挑战。

首先,云上用户需要更为丰富的业务语义消息,包括事务、定时、顺序以及死信等。为了满足用户的业务侧需求,需要在原先架构的客户端侧和 Broker侧分别进行开发,用户必须升级客户端之后才能享受新功能。

其次,上云过程需要面对更为复杂的网络环境,不同场景下需要不同类型网络的接入。有些用户为了便捷性,期望能够交付公网的接入点,让不同地域的消费者、发送者都能连接到同一个消息服务;而另一种用户为了安全性,需要内网接入点来隔离一些非法的网络请求;RocketMQ原先的架构在应对多网络类型的接入诉求时,成本是比较高的,多网络类型的接入必须同时覆盖NameServer和Broker的每一台机器才行。比如我们需要对内部 Broker进行扩容场景下,如果原先的 Broker 拥有多种类型的网络接入诉求,那么新扩容的 Broker也需要额外绑定上多种类型的网络接入点之后才能正常对外交付。

做下总结,面对上云的挑战,此前的架构逐渐暴露出了如下诸多痛点:

① 富客户端形态:客户端包含了大量企业级特性。用户必须升级客户端才能享受新功能,过程十分漫长。且同样的功能交付必须在多个多语言版本里都进行适配才能满足多语言客户端的接入,工作量巨大。

② 客户端与Broker所有节点的直连模式满足多类型网络接入的成本较高。

③ 按照队列进行负载均衡和消息拉取,后端扩缩容时会触发客户端rebalance,导致消息延迟或重复消费,消费者会有明显的感知;此外, 基于队列的模型非常容易导致一个用户饱受困扰的问题:单个故障消费者消费卡住会导致消息在服务端大量堆积。

RocketMQ5.0无状态代理模式

在这里插入图片描述

为了解决上述痛点,RocketMQ 5.0 提出了无状态代理模式。

新架构在原先的客户端和Broker中间插入了代理层。策略上是将客户端的无状态功能尽可能下移到代理层,同时也将 Broker侧的无状态功能尽可能上移到代理层。在这里,我们将客户端的原有的负载均衡机制、故障隔离、push/pop消费模型下移到了代理层,将 Broker 的访问控制、多协议适配、客户端治理以及NameServer 的消息路由能力上移到了代理层,最终打造出的代理层的丰富能力,包含访问控制、多协议适配、通用业务能力、治理能力以及可观测性等。

在构建代理层的过程中,我们必须坚持的一个原则就是:客户端和 Broker 往代理层迁移的能力必须是无状态的,这样才能保证后续代理层是可以随着承接的流量大小进行动态扩缩容的。

在这里插入图片描述

在引入无状态代理层后,RocketMQ原先客户端、Broker的直连架构就演变为上图的无状态代理模式架构:

从流量上看,代理层承接了客户端侧所有流量, Broker 和 NameServer 不再直接对用户暴露,用户唯一能看到的组件只有代理层(Proxy)。

这里,Proxy的职责包括以下几个方面:

  • 多协议适配: Proxy具备解析和适配不同协议的能力,包含 remoting 、gRPC、HTTP 以及后续可能衍生出来的MQTT和AMQP等协议。Proxy对不同协议进行适配、解析,最终统一翻译成与后端 Broker 和 NameServer 之间的 remoting协议。

  • 流量治理和流量分发: Proxy承接了客户端侧所有流量,因此能够很轻松地基于某些规则识别出当前流量的特性,然后根据一定的规则将流量分发到后端不同的 Broker集群,甚至进行精准的流量控制、限流等。

  • 功能扩展:包括访问控制比如允许哪个用户访问后端Broker集群中的哪个 Topic、消息轨迹的统一收集以及整体的可观测性等。

  • Proxy能扮演NameServer,交付给客户端查询TopicRoute的能力。

  • Proxy能够无缝兼容用户侧的Pop或者Push消费模式:在Proxy和Broker侧采用Pop消费模式来避免单个队列被锁导致消息在服务端堆积的历史遗留问题。

同时,我们也可以看到Proxy具有以下两大特性:

① 无状态,可根据用户以及客户端的流量进行水平扩缩容。

② 计算型,比较消耗CPU,因此在部署时需要尽可能给Proxy分配多些CPU。

做下总结,无状态代理模式解决了原先架构的多个痛点:

① 将客户端大量业务逻辑下移到代理层,打造出轻量客户端。同时,依托于 gRPC协议的标准化以及传输层代码自动生成的能力,能够快速适配多种语言的客户端。

② 客户端只会与Proxy层连接,针对多网络类型接入的诉求,可以将多网络类型绑定到Proxy层,由于Broker 和 NameServer不再直接对客户端暴露,转而只需对 Proxy暴露内网的连接即可,多网络类型接入的诉求可以只在Proxy这个组件就封闭掉;同时,Proxy的无状态的特性保证了多类型网络接入是与集群规模无关的。

③ 消费模式进行了无感知切换,无论客户端侧选择的是Pop还是Push消费模式,最终统一替换为Proxy与Broker侧的Pop消费模式,避免单个客户端消费卡住导致服务端消息堆积的历史问题。

RocketMQ无状态代理模式技术详解

在这里插入图片描述

新架构在客户端和 Broker 之间引入了代理层,客户端所有流量都需要多一跳网络、多经历一次序列化/反序列化的过程,这对端到端消息延迟敏感的用户是极其不友好的,因此我们设计了合并部署形态。

合并部署形态下,Proxy和 Broker 按照1:1的方式对等部署,且 Proxy和 Broker 实现进程内通信,满足低延迟、高吞吐的诉求。同时,Proxy仍然具备多协议适配的能力,客户端会与所有 Proxy建立连接进行消息收发保证能够消费到所有消息。

代码实现上,我们通过构造器来实现合并部署和分离部署的两种形态。用户可自行选择部署形态。如果用户选择合并部署的形态,则在构建 Proxy处理器之前,会先构造 BrokerController,并向 Proxy的处理器注册,本质上是为了告知Proxy处理器:后续的请求往我这个BrokeController 发;如果用户选择分离部署模式,则无须构建BrokerController,直接启动Proxy处理器即可。

在这里插入图片描述

对于这两种部署模式的比较,首先,合并部署和分离部署同时具备了多协议的适配能力,都能够解析用户侧和客户端侧的多协议请求;且具备模型抽象,能够解决富客户端带来的一系列痛点。

部署架构上,合并部署是一体化的架构,易于运维;分离部署是分层的架构,Proxy组件独立部署,Proxy和 broker按业务水位分别进行扩缩。

性能上,合并部署架构少一跳网络和一次序列化,有较低的延迟和较高的吞吐;分离部署多一跳网络和一次序列化,开销和延迟有所增加。延迟具体增加多少主要依赖于 Proxy和 Broker 之间的网络延迟。

资源调度上,合并部署状态下比较容易获得稳定的成本模型,因为组件单一;分离部署形态下Proxy是 CPU 密集型,Broker和NameServer 也逐渐退化成存储和 IO 密集型,需要分配比较多的内存和磁盘空间,因此需要进行细粒度的分配和资源规划,才能让分离部署形态资源的利用率达到最大化。

多网络类型接入成本上,合并部署成本较高,客户端需要与每一个 Proxy副本都尝试建立连接,然后进行消息收发。因此,多网络接入类型场景下,Proxy进行扩缩容时需要为每台Proxy绑定不同类型的网络;分离部署模式成本较低,仅需要在独立部署的 Proxy层尝试绑定多网络类型的接入点即可,同时是多台Proxy绑定到同一个类型的网络接入点即可。

针对业务上的选型建议:

如果对端到端的延迟比较敏感,或期望使用较少的人力去运维很大集群规模的RocketMQ部署,或只需要在单一的网络环境中使用RocketMQ的,比如只需内网访问,则建议采用合并部署的模式。

如果有多网络类型接入的诉求比如同时需要内网和公网的访问能力或想要对RocketMQ进行个性化定制,则建议采用分离部署的模式,可以将多网络类型的接入点封闭在 Proxy层,将个性化定制的改造点也封闭在Proxy层。

在这里插入图片描述

社区新推出的PopConsumer消费模式和原先的PushConsumer 消费模式存在较大区别。PushConsumer 是基于队列模型的消费模式,但存在一些遗留问题。比如单个 PushConsumer 消费卡住会导致服务端侧消息堆积。新推出的Pop消费模式是基于消息的消费模型,PopConsumer 会尝试和所有 broker 连接并消费消息,即便有一个PopConsumer消费卡住,其他正常的PopConsumer依然能从所有 broker里拉取到消息进行消费,不会出现消息堆积。

从Proxy代理层角度看,它能够无缝适配 PushConsumer 和 PopConsumer,最终将两种消费模式都映射到 Pop 消费模式,与后端 Broker 建立消费连接。具体来看,PushConsumer 里的pull请求会被转成PopConsumer 消费模式里的 pop 请求,提交位点的 UpdateConsumeOffset 请求会被转换成消息级别的 ACK 请求,SendMessageBack会被转换成修改消息的不可见时间的请求,以达到重新被消费的目的。

在这里插入图片描述

Proxy最上层为协议的适配层,通过不同的端口对客户端暴露服务,不同协议通过不同端口请求到Proxy之后,协议适配层会进行适配,通过通用的 MessagingProcessor 模块,将send、pop、ack、ChangeInvisibleTime等请求转换成后端 Remoting 协议的请求,与后端的 Broker 和NameServer建立连接,进行消息收发。

多协适配的优势有以下几个方面:

① 加速了RocketMQ的云原生化,比如更容易与Service Mesh相结合。

② 基于 gRPC 的标准性、兼容性及多协议多语言传输层代码的生成能力,打造RocketMQ的多语言瘦客户端,能够充分利用gRPC插件化的连接多路复用、序列化/反序列化的能力,让RocketMQ客户端更加轻量化,将更多精力聚焦在消息领域的业务逻辑。

在这里插入图片描述

做下技术方案的总结:

无状态代理模式通过客户端下移、Broker侧上移无状态的能力到代理层,将访问控制、客户端治理、流量治理等业务收敛到代理层,既能够满足快速迭代的诉求,又能对变更进行收敛,更好保障整个架构的稳定性:有了分层架构之后,更多业务逻辑的开发会聚焦在 Proxy层,下一层的 Broker和 NameServer 趋于稳定,可以更多地关注存储的特性。Proxy的发布频率远远高于底层 Broker 的发布频率,因此问题收敛之后,稳定性也得到了保证。

多协议适配,基于gRPC的标准性、兼容性以及多语言传输层代码生成的能力打造RocketMQ的多语言瘦客户端。

Push 到 Pop 消费模式的无感知切换,将消费位点的维护收敛到 Broker, 解决了单一消费者卡住导致消息堆积的历史遗留问题。

另外,我们也尝试探索了可分可合的部署形态,保证同一套代码可分可合,满足不同场景下对性能部署成本、易运维性的差异化诉求。在大部分的场景下,依然建议选择合并部署的形态。如果有对多网络类型接入的诉求,或对RocketMQ 有极强的定制化诉求,则建议选择分离部署的形态,以达到更好的可扩展性。

代理层无状态的特性,极大降低了适配多类型网络接入诉求的成本。

未来规划

在这里插入图片描述

未来,我们期望RocketMQ底层的Broker和NameServer 更多聚焦在存储的特性上,比如业务型消息存储的事务、定时、顺序等,快速构建消息索引、打造一致性多副本提升消息可靠性、多级存储来达到更大的存储空间等。

其次,对无状态代理层依照可插拔的特性开发,比如对访问控制、抽象模型、协议适配、通用业务能力、治理能力等按模块进行划分,使语义更丰富,可按照不同场景的诉求可插拔地部署各种组件。

最后,我们期望这一套架构能够支持阿里云上的多产品形态,致力于打造云原生消息非常丰富的产品矩阵。

加入 Apache RocketMQ 社区

十年铸剑,Apache RocketMQ 的成长离不开全球接近 500 位开发者的积极参与贡献,相信在下个版本你就是 Apache RocketMQ 的贡献者,在社区不仅可以结识社区大牛,提升技术水平,也可以提升个人影响力,促进自身成长。

社区 5.0 版本正在进行着如火如荼的开发,另外还有接近 30 个 SIG(兴趣小组)等你加入,欢迎立志打造世界级分布式系统的同学加入社区,添加社区开发者微信:rocketmq666 即可进群,参与贡献,打造下一代消息、事件、流融合处理平台。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.luyixian.cn/news_show_398728.aspx

如若内容造成侵权/违法违规/事实不符,请联系dt猫网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

安卓投屏 QtScrcpy

一、电脑安装adb 版本大于1.0.40以上 40不行 adb 1.0.41下载链接 链接:https://pan.baidu.com/s/1WIPI-p7a4ErTLFYHaTC2kw?pwdadbt 提取码:adbt 安装参考 https://blog.csdn.net/M7_xbc/article/details/122957311 二、打开无线调试并且配对 手机打…

驱动开发(10/10-林雪阵)

终端输入1--->LED1点亮 终端输入2--->LED2点亮 终端输入3--->LED3点亮 终端输入0--->LED熄灭 chdev.c (底层驱动代码&#xff09; #include <linux/init.h> #include <linux/module.h> #include <linux/fs.h> #include <linux/uaccess.h>…

【webrtc】rtp 扩展头的ID

ietf 文档地址扩展头的uri 是固定的,因此识别扩展是通过uri地址,而非ID。rtp 扩展头是有个ID的 文档的说法 : 是本地的id,15保留,只可以小于15 本地标识符值 15 保留用于将来的扩展和 不得用作标识符。如果 ID 值 15 是 遇到,它的长度字段应该被忽略,处理 整个扩展应在该…

redis之AOF和RDB持久化

写在前面 因为redis数据是基于内存的&#xff0c;为了避免服务器重启或者是宕机导致数据全部丢失&#xff0c;提供了数据持久化机制&#xff0c;即AOF(Append Only File)日志和RDB快照&#xff0c;接下来我们分别看下。 1&#xff1a;AOF 1.1&#xff1a;AOF日志的实现 首先…

(附源码)计算机毕业设计SSM政府项目管理平台

项目运行 环境配置&#xff1a; Jdk1.8 Tomcat7.0 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#xff09;。 项目技术&#xff1a; SSM mybatis Maven Vue 等等组成&#xff0c;B/S模式 M…

回顾——PCB绘制

目录 一、原理图库原理图 二、PCB库 三、PCB 一、原理图库原理图 新建工程&#xff1a;文件——New——Project——Name&#xff08;这里复制一下&#xff09;自己选择保存路径 添加文件&#xff1a; 保存工程&#xff1a;(粘贴) 绘制原理图库、原理图 侧边栏消失&…

虚拟社会、区块链和元宇宙

1986年&#xff0c;早期的互联网供应商Quantum Link和娱乐公司Lucasfilm Games发布了第一款MMO游戏名为&#xff1a;《Habitat》基于虚拟角色的社交世界&#xff0c;玩家可以通过300波特的调制解调器(每分钟0.08美元)和用户的Commodore 64(595美元&#xff0c;按今天的价格约为…

Vue 动态换肤

效果如图&#xff1a; 源代码&#xff1a; <template><div :class"[son${temp}]" class"demo3">这是四点零八分的北京<br/>一片手的海浪翻动<br/>这是四点零八分的北京<br/>一声雄伟的汽笛长鸣<br/>北京车站高大的建…

Kafka监控EFAK(Kafka-eagle)部署与踩坑详细记录

环境 阿里云服务器centoskafka 2.4.1 &#xff08;1.1以上版本都能支持&#xff0c;低版本不太清楚了&#xff09;efak 3.0.1 当前时间官网下载的最新版&#xff08;原名叫kafka-eagle&#xff09;efak官网&#xff1a;http://www.kafka-eagle.org/jdk8 部署好的UI 部署流程 …

kafka系列——安装部署,相关命令,配置文件,底层存储结构,log和index文件

点击上方“罗晓胜”&#xff0c;马上关注&#xff0c;您的支持对我帮助很大 / 前言 / Kafka是最初由Linkedin公司开发&#xff0c;用scala语言编写的&#xff0c;是一个分布式、支持分区的&#xff08;partition&#xff09;、多副本的&#xff08;replica&#xff09;&…

时光机特效在哪里?推荐这三个实用软件给你

现如今有一款时光穿梭机的特效软件非常热门&#xff0c;它具有让照片中的人变年轻或者变老的功能&#xff0c;能让我们看到过去以及未来自己的样子&#xff0c;也能给我们枯燥的生活增添一点趣味感。那么大家是不是已经迫不及待地想知道时光穿梭机特效滤镜在哪了呢&#xff1f;…

Linux学习 -- docker的commit命令和本地镜像到云端

commit命令本地镜像到云端 一、commit命令 我们在使用镜像新建容器后&#xff0c;容器只是具有简易的Linux的功能&#xff0c;不具备一些常用的功能&#xff0c;如vim功能&#xff0c;因此我们需要给容器加上一些我们需要的功能。 使用如下命令&#xff1a; docker commit提交容…

不使用第三方库怎么实现【前端引导页】功能?

前言 随着应用功能越来越多&#xff0c;繁多而详细的功能使用和说明文档&#xff0c;已经不能满足时代追求 快速 的需求&#xff0c;而 引导页&#xff08;或分步引导&#xff09; 本质就是 化繁为简&#xff0c;将核心功能以更简单、简短、明了的文字指引用户去使用对应的功能…

Oracle数据库 | SQL语句解析

个人主页&#xff1a;&#x1f497;wei_shuo的个人主页 &#x1f3c0; Hello World &#xff01;&#x1f3c0; 文章目录一.Oracle启动及登录1.1 服务手启动即关闭1.2 SQL* PLUS命令二. 表的创建和维护2.1 创建表2.2 修改表2.3 重命名表2.4 截断表2.5 删除表三. 数据完整性与约…

【C++学习】类与对象(中)

&#x1f431;作者&#xff1a;一只大喵咪1201 &#x1f431;专栏&#xff1a;《C学习》 &#x1f525;格言&#xff1a;你只管努力&#xff0c;剩下的交给时间&#xff01; 类与对象&#xff08;中&#xff09;&#x1f638;构造函数&#x1f639;概念&#x1f639;特性&…

常见数据结构-散列表(上)理论

一&#xff0c;散列表理解 散列表的英文叫“Hash Table”&#xff0c;我们平时也叫它“哈希表”或者“Hash 表”&#xff0c;散列表用的是数组支持按照下标随机访问数据的特性&#xff0c;所以散列表其实就是数组的一种扩展&#xff0c;基于数组演化而来。 散列表是通过散列函…

bp神经网络performance怎么看,BP神经网络用什么软件

1、除了MATLAB能做BP神经网络&#xff0c;还有其他什么软件能做 除了MATLAB能做BP神经网络&#xff0c;还有其他什么软件能做 理论上编程语言都可以&#xff0c;比如VB&#xff0c;C语言&#xff0c;过程也都是建模、量化、运算及结果输出&#xff08;图、表&#xff09;&…

JavaScript设计模式(一):面向对象编程 - 继承

JavaScript设计模式 - 面向对象编程灵活的语言-JavaScript用对象收编变量对象的另一种形式(函数对象)真假对象(闭包和类)一个检测类函数的祖先写的都是看到的-面向对象编程创建一个类&#xff08;三种方式&#xff09;类的属性和方法通过闭包来实现类的静态变量定义&#xff0c…

二十一、JAVA调用存储过程(Oracle专栏)

2022年9月28日16:33:11目录 &#x1f3c6;一、存储过程的创建及调用 ⭐️1.1、PLSQL编程 ⭐️1.2、程序结构 ⭐️1.3、变量 1.3.1、普通变量 1.3.2、引用型变量 1.3.3、记录型变量 ⭐️1.4、流程控制 1.4.1、条件分支 1.4.2、循环 &#x1f3c6;二、游标 ⭐️2.1、…

网状神经系统的典型特点,网状结构神经系统

脑干网状结构对肌紧张既有抑制作用也有加强作用。 选择A对。理由如下&#xff1a;网状结构中存在有抑制和加强肌紧张和肌运动区域&#xff0c;分别成为抑制区和易化区。抑制区位于网状结构的腹内侧部分。易化区位于网状结构的背外侧、脑桥被盖、中脑中央灰质及被盖。 &#x…