基于 RocketMQ 实现 AMQP 协议实践

导语

在Apache CoC 2024 杭州站大会中,腾讯云高级工程师张乐为与会者带来了精彩的演讲。围绕《基于 RocketMQ 底座实现 AMQP 协议》的背景、目标、方案设计以及几个核心技术实现做了详细的阐述。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

作者简介

张乐

腾讯高级工程师,负责腾讯云 RabbitMQ Serverless 商业化开发。

10年中间件开发经验,开源社区爱好者,Apollo、Spring Cloud Tencent PMC。

背景

AMQP 协议

AMQP(Advanced Message Queuing Protocol) 是 2004年左右由业界的几个大公司一起制定的高级消息队列协议,目标是跟 HTTP 一样广泛使用的面向消息的标准通信协议。

在这里插入图片描述

图:AMQP 模型

AMQP 核心模型

● Virtual Hosts(虚拟主机)

○ 用于多租户逻辑隔离,例如可以用于区分测试、预发、生产环境。

● Exchange(交换机)

○ 在 AMQP 协议中,生产者往 Exchange 里发送消息,消息发送到 Exchange 之后,根据 RoutingKey、BindingKey 的匹配关系把消息分发到相应的目标队列。

● Queue(队列)

○ 一组消息的集合,消费者通过拉或者推的方式从队列里消费消息。

目前市面上最主流的 AMQP 实现者是 RabbitMQ,实现的 AMQP 协议版本是 0.9.1。在 Kafka、RocketMQ 、Pulsar 等新型消息队列产品问世之前,RabbitMQ 是最流行的消息队列之一。所以 RabbitMQ 在国内外还是有大量的公司使用,例如传统的金融行业。

RabbitMQ 协议的局限性

腾讯云托管了开源版本的 RabbitMQ,为用户提供开箱即用的 RabbitMQ 产品。在运维成百上千套 RabbitMQ 集群过程中,我们也发现了开源 RabbitMQ 的一些局限性,例如以下列出的几点:

抗堆积能力弱

通常 RabbitMQ 集群由三副本组成的一个分布式集群,通过副本之间的消息复制保证消息的高可靠性。不能做到无限的水平扩容,提升集群的服务水位。导致了集群抗堆积能力弱、单集群的 TPS 上限有限。所以 RabbitMQ 一定程度上不适用于大规模的消息队列场景。

网络分区问题

RabbitMQ 支持 Raft 模式消息复制,在 Raft 模式下,容易导致网络分区的问题。

二次开发、运维难

RabbitMQ 使用 Erlang 小众语言开发,导致二次开发门槛极高,只能通过调参、重启等比较被动的方式运维 RabbitMQ。

延迟消息插件不稳定

延迟消息在消息队列产品中是使用非常广泛的功能,但是在 RabbitMQ 实现中,延迟消息插件打开之后,很容易导致集群出现 OOM 等不稳定的情况。

技术选型

基于 AMQP 的广泛性以及开源 RabbitMQ 的局限性,我们的目标是非常明确的。要实现一套完全自主可控、高可扩展性、低运维成本的 AMQP 协议的消息队列产品。

我们最终选择了基于 RocketMQ 实现 AMQP 协议,主要有下面几个点的考虑:

  1. 完全自研一套 MQ 产品,成本高、时间周期长、稳定性难保证。

  2. 目前 RocketMQ 在在线消息领域使用非常广泛,并且新版本的 RocketMQ 提供 了 LMQ、POP 等特性,使其在适配 AMQP 协议的复杂度上大大降低。并且 RocketMQ 经过多年的发展,在稳定性、性能、功能上表现都非常优异。

  3. 腾讯云有专门的 RocketMQ 团队,提供了技术保障。

AMQP On RocketMQ 系统架构

在这里插入图片描述

图:架构图

服务端侧一共分为两层。

  1. RocketMQ 存储池

a. 由多套 RocketMQ Broker 组成的消息存储池,可以通过水平垂直扩容单个 Broker 集群,或者增加更多的 Broker 集群,达到无限容量的效果。

  1. Proxy 适配层

a. 在 Proxy 层适配了 AMQP 协议, 一个 Proxy 集群等于一个 AMQP 集群。

b. 几乎无状态,可以水平横向无限扩容。

c. 一个 Proxy 集群只会绑定到一个底层的 Broker 集群。

d. Proxy 元数据存储在数据库里,多个 Proxy 集群共享数据库,通过 Proxy Id 逻辑隔离。

这种架构和最新的 RocketMQ 5 架构完全一致,可以认为是存算分离架构,便于实现 Serverless 产品形态。

核心技术点

模型映射

LMQ(Light Message Queue)

在 RocketMQ 模型中 Topic 是最核心的模型,同时也非常的”重“,消耗的资源多。当 Topic 数量增加到万级别之后,Broker 的稳定性会有比较大的影响。在 AMQP On RocketMQ 模型中, Broker 作为上层 Proxy 的共享集群,如果 AMQP 的 Queue 映射到 RocketMQ 的 Topic 就会产生大量的 Topic。RocketMQ 为了解决这个问题,支持 LMQ(Light Message Queue)队列,这种队列更加轻量,能支持到百万级别的量级。

LMQ 实现的原理是基于 RocketMQ 比较灵活的消息存储模型,如下图所示:

在这里插入图片描述

图:RocketMQ 存储模型

所有 Topic 的消息都追加写入到同一个 CommitLog 文件中,并同时维护消息索引文件组成消息队列。

通过这个模型,很容易扩展出 LMQ 能力。只需要在每条消息上增加一个属性(lmq)标识这条消息归属于哪些队列。然后通过属性就能反向聚合出队列的消息集合,如下图所示:

在这里插入图片描述

图:LMQ 模型

这种模型下,一个LMQ只是多维护了一个队列索引文件,所以非常的轻量。

最终的模型映射如下所示:

● 一个 Proxy 集群映射到 RocketMQ 的一个 Topic。

● AMQP 中的 Queue 映射到 RocketMQ 的一个 LMQ。

在这里插入图片描述

图:模型映射

收发消息核心链路

发送消息

  1. SDK 发送消息到 Proxy 层,Proxy 根据 Exchange 的 BindingKey 计算目标队列集合。

  2. Proxy 层通过 RocketMQ SDK 向 RocketMQ Topic=proxyId 发送一条消息,并且消息携带 lmq=List属性。

在这里插入图片描述

图:发送消息

消费消息

AMQP 支持两种消费模式拉和推。

在这里插入图片描述

图:消费模型

拉模式

拉模式相比于推模式更加简单,直接在 Proxy 层把 AMQP 的拉消息请求转化成 RocketMQ 的一个 POP 请求,完全无状态,透明转发即可。

推模式

推模式复杂一些,需要在 Proxy 层实现拉转推的逻辑。Proxy 层内置定时从 RocketMQ POP 消息的线程池,获取到消息后,通过长连接把消息推送给客户端。

二进制协议解析

AMQP 自定了数据帧的二进制格式,如下所示:

在这里插入图片描述

图:帧格式

在 Proxy 层需要解码、编码二进制包,这部分的工作还是非常复杂的,很容易出现不兼容的问题。因为我们的 Proxy 是用 Java 语言实现的,正好 Java 语言也有一个 AMQP 实现(QPID)已经做了这部分的工作,我们只需要实现 QPID 定义的协议接口指令即可,这样可以大大简化我们的开发工作量。

在这里插入图片描述

功能&性能

因为 AMQP 协议非常的复杂,目前我们实现的版本适配了绝大部分的核心功能。

FunctionAMQP On RocketMQRabbitMQ
Delay MessageSupportedPlugin (Unstable)
Retry MessageSupportedNot Supported
Message TrackSupportedPlugin
Transaction MessageNot SupportedSupported
Sequential messageNot SupportedSupported
Priority MessageNot SupportedSupported

性能上目前只做了初步的性能调优,基本能满足绝大部分用户的需求,后续我们会做更加深入的性能调优。

在这里插入图片描述

图:压测数据

未来展望

我们计划 25年 Q1 在腾讯云上线 RabbitMQ Serverless 形态,逐步开放给内外部用户公测使用。并在 25年年底把产品打磨的更加稳定、成熟,和开源托管版形成互补,满足不同体量的腾讯云用户诉求。

在开源方面,我们会在某一个合适的时机开源出来,一方面回馈社区,另外一方面通过社区的力量把产品打磨的更加完善。

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

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

相关文章

python成绩分级 2024年6月python二级真题 青少年编程电子学会编程等级考试python二级真题解析

目录 python成绩分级 一、题目要求 1、编程实现 2、输入输出 二、算法分析 三、程序代码 四、程序说明 五、运行结果 六、考点分析 七、 推荐资料 1、蓝桥杯比赛 2、考级资料 3、其它资料 python成绩分级 2024年6月 python编程等级考试二级编程题 一、题目要求 …

我做了一份斯坦福CS229吴恩达机器学习笔记

吴恩达教授的机器学习课程,可以说是AI领域的一块金字招牌。这门在斯坦福大学开设的课程,历经十余年,依旧是机器学习入门的经典之作。 记得当年,这门课火爆到吴恩达教授不得不将其搬到线上,结果不仅在斯坦福&#xff0c…

ABAP开发学习——SNRO

SAP凭证号码的指定分为外部给号和内部给号。 Internal number range即内部给号,指系统根据预先维护好的号码范围(只能是阿拉伯数字)依序给号,给出已有数字的下一个编号。 External number range即外部给号,后台配置时指指定一个号码范围(可以…

SpringBoot3整合Hutool-captcha实现图形验证码

文章目录 验证码需求分析:项目创建import方式的使用说明exclude方式定义接口:接口定义定义 CaptchaController前端代码在整合技术框架的时候,想找一个图形验证码相关的框架,看到很多验证码不在更新了或者是在中央仓库下载不下来,还需要多引入依赖。后面看到了Hutool **图形…

mysql-connector-java的jar包的下载方法汇总

方法一: 网址:http://mvnrepository.com/artifact/mysql/mysql-connector-java 1.进去后选择自己的版本: 2.然后再点击 3. 需要下载其他的jar包(或者依赖)都是在此网址中可以下载到的 3.1 3.2 3.3 3.4 方法二&#…

Spring Cloud Stream实现数据流处理

1.什么是Spring Cloud Stream? 我看很多回答都是“为了屏蔽消息队列的差异,使我们在使用消息队列的时候能够用统一的一套API,无需关心具体的消息队列实现”。 这样理解是有些不全面的,Spring Cloud Stream的核心是Stream&#xf…

i春秋-签到题

练习平台地址 竞赛中心 题目描述 题目内容 点击GUESS后会有辨识细菌的选择题 全部完成后会有弹窗提示 输入nickname后提示获得flag F12检查 元素中没有发现信息 检查后发现flag在控制台中 flag flag{663a5c95-3050-4c3a-bb6e-bc4f2fb6c32e} 注意事项 flag不一定要在元素中找&a…

无人机 PX4飞控 | CUAV 7-Nano 飞行控制器介绍与使用

无人机 PX4飞控 | CUAV 7-Nano 飞行控制器介绍与使用 7-Nano简介硬件参数接口定义模块连接供电部分遥控器电机 固件安装 7-Nano简介 7-Nano是一款针对小型化无人系统设备研发的微型自动驾驶仪。它由雷迅创新自主研发和生产,其创新性的采用叠层设计,在极…

怎么编译OpenWrt镜像?-基于Widora开发板

1.准备相应的环境,我使用的环境是VMware16ubuntu20.04,如图1所示安装编译所需的依赖包; sudo apt-get install build-essential asciidoc binutils bzip2 gawk gettext git libncurses5-dev libz-dev patch python3 python2.7 unzip zlib1g-…

优化表单交互:在 el-select 组件中嵌入表格显示选项

介绍了一种通过 el-select 插槽实现表格样式数据展示的方案,可更直观地辅助用户选择。支持列配置、行数据绑定及自定义搜索,简洁高效,适用于复杂选择场景。完整代码见GitHub 仓库。 背景 在进行业务开发选择订单时,如果单纯的根…

SpringBoot中设置超时30分钟自动删除元素的List和Map

简介 在 Spring Boot 中,你可以使用多种方法来实现自动删除超时元素的 List 或 Map。以下是两种常见的方式: 如果你需要简单的功能并且不介意引入外部依赖,可以选择 Guava Cache。如果你想要更灵活的控制,使用 Spring 的调度功能…

使用可视化工具kafkatool连接docker的kafka集群,查看消息内容和offset

1、下载kafkatool 下载地址Offset Explorer,下载对应系统的offset explorer 下载完,傻瓜安装即可(建议放D盘),在开始菜单输入offset找到该应用打开 打开 2、连接kafka 点击File > add new connection Bootstrap…

Docker3:docker基础1

欢迎来到“雪碧聊技术”CSDN博客! 在这里,您将踏入一个专注于Java开发技术的知识殿堂。无论您是Java编程的初学者,还是具有一定经验的开发者,相信我的博客都能为您提供宝贵的学习资源和实用技巧。作为您的技术向导,我将…

BLIP-2模型的详解与思考

大模型学习笔记------BLIP-2模型的详解与思考 1、BLIP-2框架概述2、BLIP-2网络结构详解3、BLIP-2的几点思考 上一篇文章上文中讲解了 BLIP(Bootstrapping Language-Image Pretraining)模型的一些思考,本文将讲述一个BLIP的升级版 BLIP-2&am…

java-贪心算法

1. 霍夫曼编码(Huffman Coding) 描述: 霍夫曼编码是一种使用变长编码表对数据进行编码的算法,由David A. Huffman在1952年发明。它是一种贪心算法,用于数据压缩。霍夫曼编码通过构建一个二叉树(霍夫曼树&a…

RK3568平台(中断篇)ARM中断流程

一.ARM 处理器程序运行的过程 ARM芯片属于精简指令集计算机 (RISC: Reduced Instruction Set Computing),它所用的指令比较简单,有如下特点: ① 对内存只有读、写指令 ② 对于数据的运算是在CPU内部实现 ③ 使用RISC指令的CPU复杂度小一点,易于设计 比如对于 a=a+b 这…

SpringBoot与MongoDB深度整合及应用案例

SpringBoot与MongoDB深度整合及应用案例 在当今快速发展的软件开发领域,NoSQL数据库因其灵活性和可扩展性而变得越来越流行。MongoDB,作为一款领先的NoSQL数据库,以其文档导向的存储模型和强大的查询能力脱颖而出。本文将为您提供一个全方位…

项目实战(webshop)

一、搭建靶场webshop(www.example1.com) 二、信息收集 1、获取IP winR→cmd→ping www.example1.com→显示出ip(192.168.51.128) 注:TTL为IP包的生存时间,拿到TTL我们可以大概的判断一下目标机器的操作系统,但不是很准确,因为…

初识算法 · 分治(3)

目录 前言: 归并排序 题目解析 算法原理 算法编写 求逆序对总数 题目解析 算法原理 算法编写 前言: ​本文的主题是分治,通过两道题目讲解,一道是归并排序,一道是求逆序对。 链接分别为: 912. 排…

MyBatis——#{} 和 ${} 的区别和动态 SQL

1. #{} 和 ${} 的区别 为了方便,接下来使用注解方式来演示: #{} 的 SQL 语句中的参数是用过 ? 来起到类似于占位符的作用,而 ${} 是直接进行参数替换,这种直接替换的即时 SQL 就可能会出现一个问题 当传入一个字符串时&#xff…