目录
一、云原生消息队列的定义
(1)高 SLA
(2)低成本
(3)易用性
(4)多样性
(5)标准化
二、移动云RocketMQ消息队列的功能介绍
三、RocketMQ 消息队列云原生设计与实践
四、移动云RocketMQ消息队列未来的技术演进与展望
RocketMQ消息队列作为消息交换的基础组件,已经在业界诸多的IT业务系统(比如,电子商务平台、交易平台和门户管理平台)中被广泛使用和落地。在私有云和自建IDC中心的使用场景下,IT业务系统需要接入与使用RocketMQ消息队列时,都得提需求单或工单给公司内部的RocketMQ中间件研发团队或SRE,由研发团队或SRE的同事使用批量部署工具在服务器上完成RocketMQ组件版本的部署。
随着云计算和算力网络时代的到来,RocketMQ消息中间件作为消息通信基础组件需要被云端租户和其他算力产品大规模的部署和广泛使用,承接跨AZ算力传输、数据信息交换、服务间异步解耦等重要作用。因此,RocketMQ消息中间件在面向算力网络场景的云原生实践中面临诸多的挑战(比如,集群的自适应无损弹性扩缩容、不停机热迁移、版本维护与管理、Serverless架构演进和优化服务器资源利用率)。
本文摘选自胡宗棠在RocketMQ SUMMIT 2022全球开发者峰会上发表的议题“移动云RocketMQ消息队列云原生底座的架构设计与实践应用”分享内容。
一、云原生消息队列的定义
云原生消息队列是云原生的通信基础设施。2015 年成立的 CNCF 基金会大范围推广了云原生的技术理念,并提供了一套完整的实践技术工具集,帮助开发者落地云原生理念。消息中间件在云原生的应用场景,主要是为微服务和服务网格架构提供核心的解耦、异步和削峰填谷的能力,消息队列服务还发挥着数据交换通道、事件驱动、事件总线等重要作用。
另外,云原生倡导面向高性能、可扩展和弹性化的系统架构设计,基于消息中间件的异步调用能够显著降低前端业务的响应时间,提高吞吐量;基于消息中间件还能实现削峰填谷,把慢服务分离到后置链路,提升整个业务链路的性能。
云原生时代对云服务有着更高的要求,传统的消息中间件在云原生这个大背景下如何持续进化为云原生的消息服务,我认为主要有下面这个几个方向:
(1)高 SLA
云原生应用将对消息队列这种云原生服务有更高的SLA要求,应用将假设其依赖的云原生服务具备跟云一样的可用性,不需要去建设备份链路来提高应用的可用性,降低架构的复杂度。只有做到与云一样的可用性,云在服务就在,才能称为真正的云原生服务。
(2)低成本
开源用户可以根据自己实际的业务流量需求,按需动态扩容和缩容,以更为经济节约的方式大幅降低部署消息队列所需要的服务器成本开销;
(3)易用性
在云原生时代,消息队列服务第一步将进化成为一种所见即所得、开箱即用的服务,开源用户无需通过繁琐的运维部署命令就可以轻松部署与运行消息队列服务,易用性极大的提高,真正成为应用层的通信基础设施。
(4)多样性
云原生消息队列将致力于建设大而全的消息生态,来涵盖丰富的业务场景,提供各式各样的解决方案,从而满足不同用户的多样性需求。
(5)标准化
消息队列API接口更加通用化,无任何云计算厂商的绑定;开源消息标准OpenMessaging就是一个与厂商无关、平台无关的分布式消息应用开发标准。
二、移动云RocketMQ消息队列的功能介绍
移动云 RocketMQ 消息队列基于 Apache RocketMQ 内核打造,针对云原生场景化做了深度优化和设计,,是一款具备实例级别的租户隔离、自适应流量弹性扩缩容、支持多协议(MQTT/Http/AMQP)、多维度监控报表统计和实例规格级别的弹性扩缩容等核心能力的高性能、高可靠、高灵活、低延迟的云原生消息队列产品。
作为云原生场景下的基础通信设施服务,移动云 RocketMQ 消息队列,目前已在中国移动公有云、私有云、混合云等生产环境得到了广泛实践与应用,每天消息流转达百亿条,单个实例可以稳定支撑每秒数十万条消息收发的TPS业务峰值。
移动云RocketMQ可以支持 HTTP 协议、MQTT协议和AMQP协议,提供了按量计费、资源包计费和独享实例计费三种计费方式方式。其中,按量计费为用户按照消息收发的调用次数进行收费;资源包计费为将按量计费打包成资源包形式,用户可以先进行资源包套餐的抵扣,抵扣完之后再继续按量计费;而对于SLA和消息并发性能有更为严格要求的云端租户,独享实例则通过Kubernetes编排方式为其提供RocketMQ独占式的消息中间件集群,使得租户独享此消息中间件集群提供的能力与服务。
移动云RocketMQ支持四种消息类型,分别是普通消息、顺序消息、事务消息和定时延迟消息。管控能力上,移动云RocketMQ 支持消息查询、消息轨迹、死信队列、资源报表、重置消费位点并提供丰富的OpenAPI。
移动云RocketMQ在云端主要有两种部署方式:
(1)作为公有云端的消息中间件云服务,采用Master/Slave 的架构,结合云存储(Cpeh/GlusterFs等)等,做数据的多级冗余存储备份。在其单实例下可提供数十万条消息吞吐并发的同时,可保障的消息数据满足可靠性和高 SLA,可用性可达 99.95% 。
(2)作为业务系统的消息中间件组件,RocketMQ消息队列可借助其自身Raft的多副本架构部署模式,实现消息数据存储的冗余性备份(通常来说,1份消息数据(CommitLog)有3个副本冗余备份),以保障消息可靠性。Raft模式 的部署可以实现自动故障转移和故障自愈。同时,通过使用混沌工程工具做故障注入测试时发现,它对对称网络分区和非对称网络分区都有较好的故障容忍能力。
目前,移动云端的RocketMQ独享实例规格最大可支持 30万+条/秒的 TPS 峰值。同时,我们采用OpenMessaging-Chaos混沌工程进行多种类型的故障演练,以不断完善和提升RocketMQ 消息队列对于故障的容错能力。
OpenMessaging-Chaos是一款利用模拟故障注入的方式来验证各种分布式系统一致性、高可用性和容错性的测试验证工具。我们利用OpenMessaging-Chaos来验证移动云RocketMQ消息队列的分布式可靠性、容错性和稳定性。在OpenMessaging-Chaos的测试中,消息客户端并发地向待测试的RocketMQ独享集群发送和订阅消息,中间会间隔性地对移动云RocketMQ消息队列集群进行模拟故障注入,最后给出测试结果,包括是否丢消息,是否有重复消息,集群平均故障恢复时间,是否符合预期的分区顺序性等。
这里的故障注入实验为:我们部署5个节点组成一组Raft模式的RocketMQ Broker,以Minor-kill故障注入为例进行Chaos测试。Minor-kill故障注入会随机挑选集群中少数节点进程杀死,由于杀死少数节点,即使集群不可用也能在一段时间内恢复,方便测试集群平均故障恢复时间。在该测试过程中,我们设置四个客户端并发向RocketMQ集群发送和订阅消息,故障注入时间间隔为100s,即100s正常运行,100s故障注入,一直循环,整个阶段一共持续10min。测试结束后,OpenMessaging-Chaos会给出测试结果和时延图。上图展示了整个测试过程中入队操作的时延情况。
三、RocketMQ 消息队列云原生设计与实践
在日常实际研发工作中通常会遇到这些情况:业务平台 A 的研发同事,找交付/中间件研发同事部署RocketMQ 组件(假设为RocketMQ集群A);业务平台 B 的研发同事,找交付/中间件研发同事第二个RocketMQ 组件(假设为RocketMQ集群B)。随着时间的推移,我们会遇到如下几个问题:
(1)研发/测试/生产环境中的RocketMQ 消息中间件集群越来越多且版本不通,为后续的治理和运维工作(版本升级/统一管理)带来了极大的挑战;
(2)部署N多个环境的RocketMQ消息中间件集群耗费人力和时间成本;
(3)部署RocketMQ消息中间件本身会占用较多的服务器资源,对于公司来说会带来不小的开销成本;
(4)不同的业务系统接入同一RocketMQ消息中间件集群,虽然可以通过对Topic进行ACL鉴权的方式做到逻辑隔离,但是无法做到物理隔离(容易导致因流量争抢、消息积压和负载不均衡等问题造成故障);
因此,我们对移动云RocketMQ消息队列云原生化的架构设计定义了三个目标:
(1)以 RocketMQ 为统一的云原生消息队列基础设施底座,支撑各个云端业务产品快速无缝地统一接入使用。
(2)满足一键化部署、无感知热升级、动态弹性扩缩容、高效化运维管理。
(3)实现业务流量以及Topic/实例维度等资源的逻辑/物理隔离,使其访问互不影响。
针对以上三点云原生化的目标,仅靠 RocketMQ 消息队列组件难以完全实现,还需要结合 Kubernetes 、自研Operator和Ceph等云原生的基础设施,通过 Kubernetes 的编排调度能力来真正实现。
这里有必要简单介绍下CRD(Custom Resource Definition)这个概念。Kubernetes中使用的Deployment、Service、Ingress、StatefulSet和ConfigMap等都是资源,而对于资源的创建、更新与删除等动作都会被称为 Event(事件),Kubernetes的Controller Manager负责事件的监听,且会触发相应的动作来满足期望(Spec)的效果,此方式被称为声明式,即为:用户只需关心部署其中应用的最终状态。而当资源无法满足需求时,Kubernetes 提供了CRD 和 Operator 为应用程序扩展Kubernetes已有的能力。
Operator是一种kubernetes的扩展形式,它可以帮助用户以Kubernetes的声明式API风格自定义资源对象(Custom Resource)来管理和操作部署于其中的应用与服务。目前,Operator已经成为分布式应用与服务在Kubernetes集群中部署的事实标准。 Operator 定义了一组为Kubernetes集群打包部署复杂业务应用的方式,能够解决应用和服务如何运行、部署的问题,以及出现问题时如何处理。
通过自研RocketMQ Operator、Kubernetes和Ceph,我们实现了移动云RocketMQ消息队列云原生化的三个目标:
(1)按需部署,直接使用 CR 的方式实现按需部署,让业务和应用服务一键化部署,快速启动,实现秒级的响应;大大节约原本需要通过运维手动或脚本部署的时间成本;
(2)实现有状态应用的备份还原;运行于Kubernetes集群中RocketMQ的Broker Pod节点可以在服务器上任意弹性漂移,解决消息数据的热备份迁移问题;
(3)实现了RocketMQ版本的一键化热升级,能够对接入的业务系统零感知、零损耗,不停机。
上图为移动云RocketMQ 消息队列云原生化的整体架构设计,其为部署在移动云端的业务租户提供RocketMQ独享实例的各种功能,每天消息流转达百亿条,其整体的流程如下:首先,控制台接受到业务租户创建RocketMQ独享集群的动作后,会提交自定义资源的CR请求至已部署的RocketMQ Operator中;随后,Operator会根据提交CR的内容,通过调用Kubernetes API Server,创建出RocketMQ独享集群。如上图,创建出4个Pod组成的RocketMQ消息队列独享集群(2主2从)。然后,部署于移动云端的服务器上的租户业务系统,可通过RocketMQ的SDK完成消息的发布与订阅。同时,租户可通过控制台来体验移动云RocketMQ消息队列的运维监控报表、消息轨迹、定时延迟消息、消息路由等高级特性。
此云原生的架构设计主要有以下三个关键点:
(1)存储架构设计:RocketMQ CommitLog是保存消息体内容的有状态数据文件,为解决 RocketMQ Broker Pod节点在不同宿主服务器上漂移后消息数据的可靠性和一致性,存储层采用了Ceph rdb,借助 Storage Class 实现了 PVC 的动态创建。比如,当RocketMQ独享集群里的Broker Pod漂到了其他机器上时,Broker进程也依然能够访问到原来的CommitLog文件中的消息体数据内容。
(2)Kubernetes Pod级的物理隔离与弹性化:为保证业务租户对RocketMQ 消息中间件集群的独享,我们采用基于Kubernetes的Pod编排来完成弹性扩缩容和物理隔离,这样也即保证了每个租户的业务流量相互之间无影响。不同的RocketMQ消息中间件集群采用不同的 Pod来编排,且其中的实例(Instance)通过 ClusterName 和 Topic 进行隔离。因此,无论从实例(Instance)层,还是Pod的运行时环境的角度来说,均实现了物理级别的隔离性。同时,为了减少公共组件的资源部署损耗,这里我们将NameServer组件设置为共用模式。
(3)元数据全局化共享:为解决元数据全局化后资源命名冲突问题,我们采用“Instance 和 Topic”拼接的方式来创建实际元数据名称,比如通过“Instance+Topic”的方式实现两个RocketMQ消息中间件独享集群中的Topic名称相互不重名,完成实例化(Instance)管理和 Topic 的逻辑隔离。
四、移动云RocketMQ消息队列未来的技术演进与展望
移动云 RocketMQ 消息队列未来的演进将以下三个方面展开:
(1)、移动云RocketMQ 云原生消息队列2.0版本目前已经完成内部测试,将于近期在移动云端发布上线。2.0版本会在容器和 Kubernetes 编排等云原生基础能力之上,通过自研调度算法和“CSI+LVM”容器存储技术,使得移动云RocketMQ消息队列产品支持开源社区多语SDK客户端、精简部署资源(存储层轻量化,去Ceph)、提升故障自愈和容错性能力。
(2)、移动云RocketMQ云原生消息队列的Serverless化。从消息队列与逻辑维度实现Serverless化,使其可根据业务规模自动扩缩容实例规格、队列数等逻辑资源,为云端用户实现真正的按需弹性使用,整体提升云计算服务器的利用资源。此外,我们希望可以通过增加Server端的Broker和 Proxy 实例的数量,真正实现按需扩缩容,并结合HPA Metrics 组件实时感知业务层的业务峰值 TPS 的使用流量,实现更有效率的弹性扩缩容。
(3)、计算存储分离架构的升级。在计算层实现MQTT/RocketMQ/AMQP的消息协议转换、租户认证和批量消息处理等操作;在存储层完成消息持久化(包括支持Append Only和CacheUp Read等原子语义);全新的计算存储分离架构可以充分发挥服务器硬件资源的优势,实现真正的云原生计算架构存储升级。