vivo 鲁班平台 RocketMQ 消息灰度方案

本文涉及的产品
服务治理 MSE Sentinel/OpenSergo,Agent数量 不受限
可观测可视化 Grafana 版,10个用户账号 1个月
简介: 实践是检验真理的唯一标准,我们进行了详细的灰度功能校验,分别是灰度版本订阅的topic&tag不变、灰度版本订阅的topic增加、灰度版本订阅的topic减少、灰度版本订阅的tage变化以及灰度版本订阅的topic&tag混合变化。

1.jpeg

本文作者:区二立 - vivo 技术架构总监


方案背景


2.png


RocketMQ使用广泛,技术场景下,可以用于异步解耦,比如不同系统间调用业务链上做分段式处理或使用不同语言的两个系统间的解耦;可以用于数据同步,比如基础数据通过 MQ 广播到各个业务领域,实现业务领域的提效;高并发订单或 IM 的推送服务中,可以使用MQ做削峰填谷;此外,在分布式事务中,也可以通过 MQ 做最终一致性的事务方案。


RocketMQ在业务场景下可覆盖很多系统,包括营销系统、生产制造上的各种管控系统、公共平台上人资、移动办公等流程类系统、类似于钉钉的自建IM 工具以及大数据等。


3.png


随着以微服务化为基础的数字化建设转型,完成一项业务必须串联不同团队和不同应用。而不同应用的开发和发布周期相对独立,需要对接的版本不一,因此需要灰度方案。


对于HTTP的灰度,很多时候通用的网关即可提供较好的支持,甚至简单地用 Nginx 实现也可以达到效果。微服务层,以Dubbo为例,有各种分组比如有扩展的 SPI 补充实现,可以轻松解决灰度方面的困扰。而 MQ 的灰度却没有标准支持,很多系统直接放弃了MQ灰度,因此也不得不接受一定时间段内的错误重试。


MQ技术特点

4.png


Broker是消息服务的核心,提供了消息服务最重要的计算与存储功能。消息发送时会对应一个 Topic,Topic为逻辑上的概念,内部执行往往是以 Queue 为单位。以普通消息类型的 Topic为例,Topic一般有多个 Queue,如图中的TOPIC_V_PLACE_ORDER 共有四个Queue,分别在两个 broker 里, broker a 与 broker b 里各有两个Queue。任何一条消息都必定属于四个Queue中的某一条。


每条消息内可指定 tag 标志,用于在逻辑上进一步切分 topic,如上图中的tagA、tagB。切分维度有多种,可以是IoT,也可以是增值服务类的产品order等。不同tab 表示不同分类,但它们共享一个 topic。


Queue可以理解为物理上的区分,broker的commitLog用于存放消息。commitLog不区分 Topic和Queue,不同的 Topic消息内容会按实际接收的Queue存储到其对应的broker commitLog上,该消息只会在集群中的某个 broker commitlog 中存在。


Broker commitLog是公用的,到达某一个 broker的消息都会存在同一个 commitLog上,即一个commitLog会同时保存不同topic的内容。


CommitLog达到一定大小时(一般为1G),会新建新的commitLog用于存储和接收新消息。commitLog在物理上存储具体消息,因此必然需要文件记录Queue与 commitLog存储消息之间的位置映射。minOffset(最小位移)和maxOffset(最大位移)也是存储位置中的重要概念。


ConsumeGroupID与 groupID 强关联, groupID 消费时会在 broker上记录 topic Queue的消费位移,即会根据Queue记录不同 groupID 的consumerOffset。


5.png


无论是生产者还是消费者,MQ都使用 groupID 表示交互的角色。在集群消费的情况下,使用同一个 groupID 的两个 client 会做Queue的消费订阅分配,一般会尽量采取平分的方式。而独立的消费组比如上图中GID_V_PAYMENT,会独占 topic中的 4 条Queue。消费组之间相互独立、互不干扰,有各自的消费位移点。


不同的 RocketMQ 实例都有独立的 clientID,作为唯一标识与 broker打交道。


6.png


提交消费位点时,只能提交该消费位点前都已完成消息位移的消息。如上图,3、4两条消息都已被消费线程处理完成,但2依然在处理中,因此实际触发的提交位点为1。消息2完成处理后,会触发消息4的提交。


7.png


不同的 groupID 之间互相绝缘,但同一个 groupID 却会相互影响。订阅关系指标记了当前应用实例的 groupID 订阅了哪些 Topic(或topic的tag)。每一个应用实例或clientID 的订阅关系都会随着心跳包一起发送到 broker上,并在 broker上以 groupID 作为 key 来存储。


每个broker每次接收到不同实例的心跳包时,都会按 groupID 的维度校验、替换订阅关系,即同一个 groupID 的订阅关系会被替换。同一个 groupID 在不同应用实例、不同 clientID ,只要订阅的 Topic和 tag 有任何不同,都会被最后到来的心跳包的订阅关系覆盖。


如果在不同的应用实例中使用同一个 groupID ,而实例因版本原因导致订阅 Topic发生变化,则两组实例共存时会互相干扰,导致有些应用实例收不到想要的消息或收到错误的消息。而订阅关系是影响 MQ 灰度方案的核心因素。


8.png


上图clientID_001 和clientID_002同属一个消费组GID_C_INVENTORY, clientID_001订阅了TOPIC_A,clientID_002 订阅TOPIC_B,都使用同一消费组执行订阅,因此,按照分配策略,它们会被交叉分配。分配结果可能是clientID_001 和clientID_002平分TOPIC_A的两条Queue, 也可能会平分TOPIC_B的两条Queue,从而导致异常。这就是订阅方式不一致导致的分配错乱以及处理错乱。


常见灰度方案


9.png


常规的灰度方案一般都会选择不同的消费组,处理方式有影子 Topic、Tag过滤以及userProperty过滤。以上几种处理方式都会存在一些缺陷:比如如何保证所有灰度消息都被消费完毕?灰度需要切换时,如何保证灰度消息是被灰度环境消费?灰度订阅切换为正常订阅关系的时候,如何确认消费位点,如何衔接才能保证消息不丢失?此外,运维人员可能对RocketMQ或应用内部逻辑不清楚,实际的操控对运维人员而言也是巨大的挑战。


鲁班灰度方案


10.png


鲁班灰度方案的核心解决思路是将Queue隔离使用。


Queue是 Topic的实际执行单元,一个Topic有多个Queue。可以选择一部分Queue用于灰度,灰度Queue的数量、开始位置等可以在具体的实现里进行定义。如上图,首尾两个Queue专门用于灰度。因此,我们只需保障生产者与消费者的灰度与正常环境隔离使用即可,灰度环境的消息只从灰度的Queue里取,正常环境的消息从正常环境的Queue里拉取。


消费者中无论是灰度还是正常的应用集群,都使用同一个消费组。这会导致订阅关系非常容易不一致。针对于此,我们的解决方案是改造订阅关系。


11.png


Broker的订阅关系维护在 ConsumerGroupInfo 里,其中 subscriptionTable 负责维护 groupID 发送来的订阅心跳包。如果心跳包的订阅关系不一样,则会进行替换。我们新增了graySubscriptionTable 类,专门负责维护灰度的订阅关系。虽然是同一个groupID,但使用不同的类来分别维护灰度和非灰度的订阅关系。


12.png


生产者的发送策略如下:首先判断目标topic是否有灰度消费者,再判断当前消息是否属于灰度范围。如果是,则将灰度消失投递到灰度的Queue里;否则,投递到正常的Queue。

13.png


消费者按灰度拉取,正常集群只平分正常的Queue,灰度集群只平分灰度的Queue。如上图,ClientID_001与ClientID_002 只会分享正常的Queue,而ClientID_003与ClientID_004只分享灰度的Queue,他们共用一个消费组。


如果本消费组使用的topic没有灰度,但由于其他消费组影响涉及到灰度topic,则它也会平分拉取灰度的Queue。此外,如果topic没有涉及灰度集群,则灰度Queue会空置不使用,消费者不拉取,生产者不发送。将灰度集群切换为正常集群时,原先灰度的集群会保证将灰度Queue消费完成后才真正进行切换,业务上动态切换服务时,MQ 会自动根据实际消费进度进行细节上的管控,保障所有消息不丢弃。


14.png


除了业务灰度标识外,MQ也有自己的灰度标识需要处理,存储于Namesrv。生产者和消费者获取 Topic路由消息都由Namesrv提供,这也意味着生产者和消费者已经与Namesrv建立了连接。可以通过定期将灰度消息更新到Namesrv上,生产者也会定期将灰度信息拉到本地来打通整个链路。


Namesrv存储灰度关系时,需要一个有状态的数据库来进行保存。


15.png


如果灰度期间的延时消息在灰度结束后才投递,则会投递到正常Queue。延时消息临时存在数据库里,能够支持比较细粒度的延时定义。


全局顺序消息会由一条Queue变成两条Queue。我们修改了创建Queue的定义,灰度切换回正常环境时,会保证将灰度的消息处理完以后再处理正常的消息。


细节上的控制主要依赖灰度开关grayFlag和graySwitch两个标识位进行控制。


graySwitch标志使用灰度的逻辑以及平分所有 Topic里Queue的逻辑,能够兼容不参与灰度的应用,可以平分所有受其他灰度消费组影响的 Topic的所有Queue。


grayFlag 用于标记本实例是否为灰度实例,这会影响到订阅关系的保存。它会先查看graySwitch,再进行自己的判断。


灰度场景校验


实践是检验真理的唯一标准,我们进行了详细的灰度功能校验,分别是灰度版本订阅的topic&tag不变、灰度版本订阅的topic增加、灰度版本订阅的topic减少、灰度版本订阅的tage变化以及灰度版本订阅的topic&tag混合变化。


加入 Apache RocketMQ 社区


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

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


16.jpeg

微信扫码添加小火箭进群


另外还可以加入钉钉群与 RocketMQ 爱好者一起广泛讨论:


17.png

钉钉扫码加群


关注「Apache RocketMQ」公众号,获取更多技术干货

相关实践学习
RocketMQ一站式入门使用
从源码编译、部署broker、部署namesrv,使用java客户端首发消息等一站式入门RocketMQ。
消息队列 MNS 入门课程
1、消息队列MNS简介 本节课介绍消息队列的MNS的基础概念 2、消息队列MNS特性 本节课介绍消息队列的MNS的主要特性 3、MNS的最佳实践及场景应用 本节课介绍消息队列的MNS的最佳实践及场景应用案例 4、手把手系列:消息队列MNS实操讲 本节课介绍消息队列的MNS的实际操作演示 5、动手实验:基于MNS,0基础轻松构建 Web Client 本节课带您一起基于MNS,0基础轻松构建 Web Client
相关文章
|
21天前
|
消息中间件 存储 Kafka
【深入浅出 RocketMQ原理及实战】「底层源码挖掘系列」透彻剖析贯穿一下RocketMQ和Kafka索引设计原理和方案
【深入浅出 RocketMQ原理及实战】「底层源码挖掘系列」透彻剖析贯穿一下RocketMQ和Kafka索引设计原理和方案
42 1
|
30天前
|
消息中间件 Kubernetes Docker
KubeSphere 核心实战之三【在kubesphere平台上部署ElasticSearch、应用商店部署RabbitMQ和应用市场部署Zookeeper】(实操篇 3/4)
KubeSphere 核心实战之三【在kubesphere平台上部署ElasticSearch、应用商店部署RabbitMQ和应用市场部署Zookeeper】(实操篇 3/4)
37 0
|
2月前
|
Java 物联网 网络安全
mqtt问题之STM32F103GPRS模组如何接入物理网平台
MQTT接入是指将设备或应用通过MQTT协议接入到消息服务器,以实现数据的发布和订阅;本合集着眼于MQTT接入的流程、配置指导以及常见接入问题的解决方法,帮助用户实现稳定可靠的消息交换。
72 2
|
11月前
|
消息中间件 测试技术 RocketMQ
面试官:使用 RocketMQ 怎么进行灰度发布?
今天来聊一聊 RocketMQ 的灰度方案。 灰度发布是指在黑与白之间,平滑过渡的一种发布方式。在大流量的系统中,如果一次升级改造范围比较大,或者影响内容不太确定,一般会采用切量的方式进行升级,这样可以减少生产变更带来的影响。
|
11月前
|
消息中间件 移动开发 运维
《2023云原生实战案例集》——04 互联网——小七手游 MQTT构筑运营平台与游戏端的交互通道
《2023云原生实战案例集》——04 互联网——小七手游 MQTT构筑运营平台与游戏端的交互通道
|
12月前
|
消息中间件 RocketMQ
RocketMQ平台的消息灰度方案(3)
RocketMQ平台的消息灰度方案
206 0
|
12月前
|
存储 消息中间件 数据库
RocketMQ平台的消息灰度方案(2)
RocketMQ平台的消息灰度方案
399 0
RocketMQ平台的消息灰度方案(2)
|
12月前
|
存储 消息中间件 算法
RocketMQ平台的消息灰度方案(1)
RocketMQ平台的消息灰度方案
443 0
|
消息中间件 算法 Java
弥补延时消息的不足,RocketMQ 基于时间轮算法实现了定时消息!
弥补延时消息的不足,RocketMQ 基于时间轮算法实现了定时消息!
604 1
弥补延时消息的不足,RocketMQ 基于时间轮算法实现了定时消息!
|
消息中间件 Apache RocketMQ
《万亿级数据洪峰下的消息引擎——Apache RocketMQ》电子版地址
万亿级数据洪峰下的消息引擎——Apache RocketMQ
310 0
《万亿级数据洪峰下的消息引擎——Apache RocketMQ》电子版地址

相关产品

  • 云消息队列 MQ