共计 5606 个字符,预计需要花费 15 分钟才能阅读完成。
编者荐语:
文章作者为中国移动云能力核心,文章转载已受权。本文将具体解析基于 Apache Pulsar 的云原生音讯队列 AMQP 背景与整体设计等深度内容。
以下文章来源于苏研大云人,作者云原生中间件团队
情谊提醒:全文 5000 多文字,预计浏览工夫 3 分钟
一、自研音讯队列中间件 AMQP 的背景
随着公司私有云业务继续倒退和用户数量的一直增长,数据量和申请量也在急剧增长,音讯队列作为必不可少的通信组件,面临的压力也在日益增长。在对音讯队列的组件保护中咱们发现:OpenStack 应用的音讯队列 RabbitMQ 存在一些问题,比方音讯易失落,集群稳定性差,问题排查艰难等。诸多难以解决的问题使咱们萌发了寻求代替开源 RabbitMQ 音讯队列的想法;另一方面,支流云服务厂商,如阿里云、华为云、天翼云等均已提供 AMQP 协定反对的音讯队列产品,而咱们短少自研对标产品。基于以上两点,团队开始自研一款高性能、高牢靠、高稳固,反对 AMQP 协定的音讯队列产品。
咱们的需要
综合云上产品和挪动云组件的需要,整顿了音讯队列 AMQP 的几大外围需要如下:
- 具备高吞吐量,低提早,高牢靠的能力;
- 能依据需要进行无限度的扩容,缩容;
- 对于上云产品来说,须要具备多租户隔离的能力;
- 具备海量音讯沉积能力,并且音讯的沉积不会影响性能和稳定性;
- 反对 AMQP 协定,兼容 AMQP 协定的客户端(比方,开源 RabbitMQ SDK);
- 具备运维部署能力,数据迁徙的便利性,具备高效的集群部署、迁徙效率。
开源产品调研
在产品设计之初,研发团队次要调研了两款实现了 AMQP 协定的开源产品:RabbitMQ 和 Qpid。因为 Qpid 在性能方面体现不佳被排除在外,RabbitMQ 性能高、应用范围广,然而不合乎咱们的需要应用场景,有如下几个起因:
- 长久化音讯性能较差。为了保障音讯不失落且音讯可回溯,须要将音讯长久化存储,通过测试 RabbitMQ 的长久化音讯性能较差,不满足咱们的需要,详见第四章节的性能测试比照。
- 为了保障音讯不失落,能够应用 RabbitMQ 的镜像队列,镜像队列的机制就是音讯多正本保留在多节点的内存中,通过测试发现,在开启镜像队列的场景下,会呈现两方面的问题:首先是集群稳定性较差,其次是音讯沉积会导致内存溢出。
- 问题排查的困难性,RabbitMQ 的编程语言是 Erlang,这种编程语言较为小众。RabbitMQ 的源码艰涩难懂,导致呈现问题时,排查艰难,且 RabbitMQ 没有实时音讯追踪的能力,须要开启音讯追踪的插件,无奈及时回溯呈现问题的音讯。
基于以上起因,咱们开始音讯队列 AMQP 的自研。
二、音讯队列 AMQP 整体设计
计算存储拆散的架构
思考到高稳定性、高可靠性和高吞吐量等诸多设计指标,研发团队最终决定采纳合乎云原生设计理念的计算存储拆散架构。
计算存储耦合和计算存储拆散有如下几个方面的比照:
当存储和计算耦合在一个集群中时,存在如下的一些问题:
- 在不同的利用或者倒退期间,须要不同的存储空间和计算能力配比,使得机器的选型会比较复杂;
- 当存储空间或计算资源有余时,只能同时对两者进行扩容,导致扩容的经济效率比拟低(另一种扩容的资源被节约了);
- 在云计算场景下,不能实现真正的弹性计算,因为计算集群中也有数据,敞开闲置的计算集群会失落数据。
针对计算存储耦合带来的一些问题,研发团队也调研了具备计算存储拆散能力的开源音讯队列 Apache Pulsar。
在 Pulsar 的架构中,计算和数据存储是独自的两个组件:
计算层也就是 Broker,Pulsar 的 Broker 不间接存储音讯实体数据,次要负责解决 Consumer 和 Producer 相干的连贯申请解决等,如果业务上 Consumer 和 Producer 特地的多,能够独自扩大这一层。
数据存储也就是 Bookie,Pulsar 应用了 Apache BookKeeper 作为存储反对,BookKeeper 是一个提供日志条目流存储长久化的服务框架,计算层应用时不用过多的关怀存储细节。
联合音讯队列 AMQP 的利用场景以及剖析面向的客户群体,咱们抉择 Pulsar 这种计算存储拆散的音讯队列作为原型进行音讯队列 AMQP 的定制化开发。在调研 Pulsar 以及与 Puslar 社区深刻沟通之后发现 Pulsar 现有的 Protocol Handler 机制十分合乎咱们这种定制化开发的需要,Protocol Handler 协定解决插件能够利用 Pulsar 现有的一些组件(例如 服务发现组件 -Topic LookUp、分布式日志库 -ManagedLedger、生产进度治理组件 -Cursor 等)来帮忙咱们实现一些逻辑解决。
因而 Pulsar 的 Protocol Handler 就成为了咱们音讯队列 AMQP 定制化开发的根底。更多 Protocol Handler 的介绍可参考 Pulsar PIP-41。
(https://github.com/apache/pul…)
音讯队列 AMQP 整体架构如上图所示,开发的重点就在于 AMQP Protocol Handler 的通信层协定的解析解决、AMQP 0-9- 1 协定模型与 Pulsar 模型之间的映射、多租户的反对以及最外围的发送生产流程的解决。
外围性能点设计
- 音讯的存储
音讯队列 AMQP 的存储设计借鉴了 RabbitMQ,最终实现利用 Pulsar 的 PersistentTopic 来实现具体的实体数据以及索引数据的存储。
1、RabbitMQ 的音讯存储模型
RabbitMQ 的音讯长久化理论包含两局部:队列索引 (rabbit_queue_index) 和音讯存储(rabbit_msg_store)。
rabbit_queue_index 负责保护队列中落盘音讯的信息,包含音讯的存储位点、是否曾经提交给消费者、是否已被消费者 ACK 等,每个队列都有一个与之对应的 rabbit_queue_index。
rabbit_msg_store 以键值对的模式存储音讯,每个节点有且只有一个,该节点上的所有队列共享该文件。从技术层面讲 rabbit_msg_store 又能够分为 msg_store_persistent 和 msg_store_transient,其中 msg_store_persistent 负责长久化音讯的存储,不会失落;而 msg_store_transient 负责非长久化音讯的存储,重启后音讯会失落。
2、BookKeeper 提供存储反对
Pulsar broker 中的 ManagedLedger 实现了对 BookKeeper 存储层的封装,利用 ManagedLedger 能够实现音讯的长久化、读取以及生产进度治理。
3、如何利用 Pulsar 现有的模型实现 exchange 以及 queue 的对应
AMQP 0-9- 1 引入了一些根底概念,例如 Exchagne,Queue 和 Router。这些与 Pulsar 的模型有着较大的区别。因而,咱们须要采纳一种建模映射形式,将现有 Pulsar 中对于 Topic 的公布 / 订阅模型与 AMQP 通信协议中的业务模型映射到一起。
AmqpExchange
AmqpExchange 蕴含一个原始音讯 Topic,用来保留 AMQP Producer 发送的音讯。AmqpExchange 的 Replicator 会将音讯解决到 AMQP 队列中。Replicator 是基于 Pulsar 的长久化游标,能够确保胜利将音讯发送到队列,而不会失落音讯。
AmqpMessageRouter
AmqpMessageRouter 用于保护音讯路由类型以及将音讯从 AmqpExchange 路由到 AmqpQueue 的路由规定。路由类型和路由规定这些元数据都长久化在 Pulsar 的 ManagedLedger 中。所以就算 Broker 重启,咱们也能够复原 AmqpMessageRouter。
AmqpQueue
AmqpQueue 提供一个索引音讯 Topic,用来存储路由到这个队列的 IndexMessage。IndexMessage 由原始音讯的 ID 和存储音讯的 Exchange 的名称组成。当 AmqpQueue 向 Consumer 发送音讯时,AmqpQueue 会依据 IndexMessage 读取原始音讯数据,而后将其发送给 Consumer。
- 多租户的反对
作为一种企业级的音讯零碎,Pulsar 的多租户能力可满足下列需要:
- 保障不同租户之间的隔离
- 针对资源利用率强制施行配额
- 提供每租户和零碎级的安全性
- 确保低成本运维以及尽可能简略的治理
Pulsar 多租户的个性,在 topic 的 URL 映射上充沛浮现,构造如下:
AMQP 0-9- 1 的协定定义中,VirtualHost 是资源隔离的根本单位,和 Pulsar 的这种多层级的模型不能有完全一致的对应关系,在咱们的实现中,挪动云 AMQP 音讯队列引入了 Instance 的概念,对应到 Pulsar 中的 Tenant,组件版本应用固定的 Tenant,Pulsar 中的 Namespace 则对应到 AMQP 中的 VirtualHost。其中组件版本的对应图如下所示:
- 音讯流转过程
- 当 Producer 发送音讯到 AmqpExchange,AmqpExchange 将音讯长久化到 Pulsar Topic (咱们称之为存储原始音讯的 Topic)。
- AmqpExchange 的 Replicator 会将消息传递给 Router。
- Router 判断是否须要将音讯路由给 AmqpQueue。如果是,会将原始音讯的 ID 存入 AmqpQueue 的 Topic 中(咱们称之为存储索引音讯的 Topic)。
- AmqpQueue 将消息传递给 Consumer。
三、音讯队列 AMQP 和 RabbitMQ 比拟
云原生
云原生的 ” 原生 ” 即软件设计之初就思考到了在云端部署的可能,音讯队列 AMQP 采纳计算存储拆散的外围架构,可能充分利用分布式、弹性伸缩的云端资源。
传统架构下的音讯队列如 RabbitMQ,将音讯存储在本地,Broker 组件需承担音讯散发和存储的双重性能;这使得 Broker 并非无状态服务,不具备弹性伸缩的能力。
而自研音讯队列 AMQP 通过计算存储拆散的架构,将 Broker 的角色进一步拆分为用于音讯散发的 Broker 和用于音讯存储的 Bookie,从而将 Broker 打造成无状态服务,以实现 Broker 的弹性伸缩。
音讯可靠性
音讯的不失落通常由两个方面保障:首先音讯须要长久化到磁盘中,其次长久化音讯须要保留多正本以晋升音讯队列的容错能力。相较于音讯队列 RabbitMQ,自研 AMQP 在音讯可靠性的保障方面具备以下劣势:
RabbitMQ 长久化音讯采纳异步刷盘机制,无奈保障断电、硬件故障等极其状况下数据的不失落;音讯队列 AMQP 原生反对音讯同步刷盘,能够保障除磁盘损坏的任何极其故障场景下,音讯的不失落。
RabbitMQ 仅在开启镜像队列时才可能进行音讯的多正本同步;而音讯队列 AMQP 原生反对音讯的多正本保留,局部节点磁盘损坏状况下,数据也可能从正本中复原进去。
RabbitMQ 在开启音讯长久化和镜像队列时,性能很差,无奈满足高性能的需要;而音讯队列 AMQP 通过文件的程序读取和音讯的缓存机制,仍能保障极高的性能。
容错
容错指集群中局部节点产生故障的时候,集群的可用性。
RabbitMQ 的容错性不高,在产生网络分区的状况下,会导致数据失落和集群的不可用,尤其是在配置镜像队列的状况下。
而音讯队列 AMQP 各个组件都能够独立的容错。Broker 是无状态服务,当产生谬误的时候,Queue 就会转移到其余 Broker,不会影响音讯收发。Bookie 尽管有状态,然而并无主从之分,只有音讯的正本足够多,即便局部 Bookie 宕机或者不可用的状况下,服务仍然能够失常运行。
可维护性
相较于 RabbitMQ,自研 AMQP 提供更加欠缺的运维监控零碎,对于零碎的各项指标,比方 TPS、容量、连贯状态、消费者状态等各项指标均有具体的监控,同时提供欠缺的阐明文档以应答可能呈现的各类问题,便于故障排查。
RabbitMQ 不具备实时音讯追踪能力,无奈及时回溯呈现问题的音讯;而 AMQP 具备音讯追踪的性能,保障所有音讯可追溯,为问题的排查提供了便当。
RabbitMQ 采纳 Erlang 语言,较为小众且艰涩难懂,很难进行源码级别的问题排查;而 AMQP 为自研中间件,所有问题都能够通过代码剖析排查解决。
四、性能
在同样的环境下,对音讯队列 AMQP 和 RabbitMQ 的单机性能进行测试:
音讯体大小:1KB
exchange 数量:1 个
queue 数量:1 个
音讯是否长久化:是
通过创立 1 个 Queue,1 个 Exchange,发送 1KB 的音讯,比照音讯队列 AMQP 和 RabbitMQ 的性能,失去上述的折线图,从上图能够看出,在等同测试条件下,音讯队列 AMQP 的性能体现远高于 RabbitMQ。
五、总结
目前音讯队列 AMQP 曾经正式上线挪动云,欢送大家订购应用。
(https://ecloud.10086.cn/home/…)
另外音讯队列 AMQP 组件版本替换 OpenStack 中 RabbitMQ 也曾经实现测试环境的验证工作,后续会在挪动云生产环境中作为 OpenStack 组件的通信组件应用。
参考资料
1、Apache Pulsar 官网:https://pulsar.apache.org/doc…
2、《RabbitMQ 实战指南》
END
作者简介
张浩
中国移动云能力核心中间件开发工程师,音讯队列 AMQP 研发负责人,在消息中间件以及分布式缓存畛域有丰盛的教训。
王少杰
中国移动云能力核心软件开发工程师,次要负责挪动云音讯队列产品研发、性能调优和保护工作,在 RocketMQ,Pulsar,RabbitMQ 等方面有丰盛的实际和优化教训。
欢送投稿
Apache Pulsar 社区欢送大家踊跃投稿,心愿这里成为大家获取 Pulsar 教训与常识分享的平台,并帮忙更多的社区小伙伴深刻理解 Pulsar。扫码增加 Bot 好友即可联系投稿👇
点击链接拜访原文。