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

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

本文作者:区二立 – vivo 技能架构总监

计划背景

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

RocketMQ运用广泛,技能场景下,能够用于异步解耦,比方不同体系间调用事务链上做分段式处理或运用不同言语的两个体系间的解耦;能够用于数据同步,比方根底数据经过 MQ 广播到各个事务领域,完结事务领域的提效;高并发订单或 IM 的推送服务中,能够运用MQ做削峰填谷;此外,在分布式事务中,也能够经过 MQ 做最终一致性的事务计划。

RocketMQ在事务场景下可掩盖许多体系,包括营销体系、出产制作上的各种管控体系、公共平台上人资、移动工作等流程类体系、类似于钉钉的自建IM 工具以及大数据等。

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

跟着以微服务化为根底的数字化建设转型,完结一项事务必须串联不同团队和不同运用。而不同运用的开发和发布周期相对独立,需求对接的版别不一,因而需求灰度计划。

对于HTTP的灰度,许多时候通用的网关即可供给较好的支撑,甚至简略地用 Nginx 完结也能够达到效果。微服务层,以Dubbo为例,有各种分组比方有扩展的 SPI 补充完结,能够轻松处理灰度方面的困扰。而 MQ 的灰度却没有标准支撑,许多体系直接抛弃了MQ灰度,因而也不得不接受必定时间段内的过错重试。

MQ技能特点

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

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。

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

无论是出产者仍是顾客,MQ都运用 groupID 表示交互的人物。在集群消费的情况下,运用同一个 groupID 的两个 client 会做Queue的消费订阅分配,一般会尽量采取平分的方法。而独立的消费组比方上图中GID_V_PAYMENT,会独占 topic中的 4 条Queue。消费组之间彼此独立、互不干扰,有各自的消费位移点。

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

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

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

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

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

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

假如在不同的运用实例中运用同一个 groupID ,而实例因版别原因导致订阅 Topic发生改变,则两组实例共存时会相互干扰,导致有些运用实例收不到想要的音讯或收到过错的音讯。而订阅联系是影响 MQ 灰度计划的中心要素。

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

上图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,从而导致反常。这便是订阅方法不一致导致的分配错乱以及处理错乱。

常见灰度计划

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

常规的灰度计划一般都会挑选不同的消费组,处理方法有影子 Topic、Tag过滤以及userProperty过滤。以上几种处理方法都会存在一些缺陷:比方怎么确保一切灰度音讯都被消费结束?灰度需求切换时,怎么确保灰度音讯是被灰度环境消费?灰度订阅切换为正常订阅联系的时候,怎么承认消费位点,怎么衔接才能确保音讯不丢失?此外,运维人员可能对RocketMQ或运用内部逻辑不清楚,实践的操控对运维人员而言也是巨大的应战。

鲁班灰度计划

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

鲁班灰度计划的中心处理思路是将Queue隔离运用。

Queue是 Topic的实践履行单元,一个Topic有多个Queue。能够挑选一部分Queue用于灰度,灰度Queue的数量、开始方位等能够在详细的完结里进行界说。如上图,首尾两个Queue专门用于灰度。因而,咱们只需保障出产者与顾客的灰度与正常环境隔离运用即可,灰度环境的音讯只从灰度的Queue里取,正常环境的音讯从正常环境的Queue里拉取。

顾客中无论是灰度仍是正常的运用集群,都运用同一个消费组。这会导致订阅联系非常简单不一致。针对于此,咱们的处理计划是改造订阅联系。

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

Broker的订阅联系保护在 ConsumerGroupInfo 里,其间 subscriptionTable 担任保护 groupID 发送来的订阅心跳包。假如心跳包的订阅联系不一样,则会进行替换。咱们新增了graySubscriptionTable 类,专门担任保护灰度的订阅联系。虽然是同一个groupID,但运用不同的类来分别保护灰度和非灰度的订阅联系。

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

出产者的发送战略如下:首要判别方针topic是否有灰度顾客,再判别当前音讯是否归于灰度规模。假如是,则将灰度消失投递到灰度的Queue里;不然,投递到正常的Queue。

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

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

假如本消费组运用的topic没有灰度,但由于其他消费组影响触及到灰度topic,则它也会平分拉取灰度的Queue。此外,假如topic没有触及灰度集群,则灰度Queue会空置不运用,顾客不拉取,出产者不发送。将灰度集群切换为正常集群时,原先灰度的集群会确保将灰度Queue消费完结后才真正进行切换,事务上动态切换服务时,MQ 会主动依据实践消费进展进行细节上的管控,保障一切音讯不丢掉。

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

除了事务灰度标识外,MQ也有自己的灰度标识需求处理,存储于Namesrv。出产者和顾客获取 Topic路由音讯都由Namesrv供给,这也意味着出产者和顾客已经与Namesrv建立了连接。能够经过定时将灰度音讯更新到Namesrv上,出产者也会定时将灰度信息拉到本地来打通整个链路。

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

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

假如灰度期间的延时音讯在灰度结束后才投递,则会投递到正常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 即可进群,参加奉献,打造下一代音讯、事件、流交融处理平台。

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

微信扫码增加小火箭进群

别的还能够参加钉钉群与 RocketMQ 爱好者一同广泛评论:

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

钉钉扫码加群

重视「Apache RocketMQ」公众号,获取更多技能干货