大家好,我是君哥。

今天来聊一聊 RocketMQ 的灰度方案。

灰度发布是指在黑与白之间,平滑过渡的一种发布方式。在大流量的系统中,如果一次升级改造范围比较大,或者影响内容不太确定,一般会采用切量的方式进行升级,这样可以减少生产变更带来的影响。

如上图,对 ServiceA 这个服务进行升级,采用灰度发布,先升级 Server5,一周后如果没有问题,升级 Server4 和 Server 3,再运行一周没有问题,把剩下两个节点都升级。

上面的案例是一个 RPC 的调用。但如果使用消息队列该怎么做呢?使用消息队列,并不能使用网关来进行流量转发。这里需要分不同场景进行分析。

1 只升级消费者

这是最简单的情况,比如只有消费者修改了消费逻辑,就是 RPC 调用的情况类似,我们只要把消费者进行灰度发布就可以。如下图:

2 生产者也升级

下面是一个订单的实体类,我们新加了一个属性,订单生成时间

public class Order {private Long id;private Long userId;private Long productId;private Integer count;private BigDecimal payAmount;/**订单状态:0:创建中;1:已完结*/private Integer status;/**新加属性,订单生成时间*/private String createTime;
}

消费端的改造是需要对 createTime 这个属性进行处理。

2.1 消费端过滤

在生产者的 Order 类中增加 createTime 属性,如果我们直接使用 createTime 属性来过滤,消费者并不能实现灰度,因为所有的消费者都可能会拉取到带有 createTime 属性的消息。

RocketMQ 中 Message 的定义如下:

public class Message implements Serializable {private String topic;private int flag;private Map<String, String> properties;private byte[] body;private String transactionId;
}

可以在 properties 属性中增加一个灰度标识,比如生产者发送消息的时候封装如下:

Message msg = buildMessage(topic);
msg.putUserProperty("gray", "true");

注意:也可以在 SendMessageHook 这个钩子函数中定义。通过这种方式可以在消费端新增加一个灰度 Consumer Group,用来对灰度消息则进行消费。如下图:

对于灰度 Consumer Group 判断到 gray 属性是 true 时进行消费,而对于普通 Consumer Group,判断到 gray 属性不等于 true 时再进行消费。这里可以借助 RocketMQ 客户端的 FilterMessageHook,代码如下:

defaultMQPushConsumerImpl.registerFilterMessageHook(new FilterMessageHook() {@Overridepublic String hookName() {return "filterHook";}@Overridepublic void filterMessage(FilterMessageContext context) {List<MessageExt> messages = context.getMsgList();context.setMsgList(messages.stream().filter(m -> StringUtils.equals(m.getProperty("gray"),"true")).collect(Collectors.toList()));}
});

不过这样会有两个问题,灰度和正常的两个 Consumer Group 相当于是广播组

  1. 两个组都要对所有的消息进行拉取,比如本来使用灰度发布计划切 10% 的流量,但实际上全部流量都切过去了,只是根据属性做了判断。这让消费端整体承担了两倍的压力;

  2. 因为两个消费者组都要去 Broker 拉取消息,Broker 的压力也增加了一倍。

2.2 Broker 过滤

2.2.1 使用 tag 过滤

如果一个 Consumer 不订阅一个 Topic 中的全部消息,可以通过 Tag 来过滤。比如一个 Consumer 订阅了 TopicA 这个 Topic 中的 Tag1 和 Tag2 这两个 tag,那这个 Consumer 的订阅关系如下图:

SubscriptionData 这个对象封装了 Topic、tag 以及所订阅 tag 的 hashcode 集合。

Consumer 发送拉取消息请求时,会把订阅关系传给 Broker(Broker 解析成 SubscriptionData 对象),Broker 使用 consumequeue 获取消息时,首先判断判断最后 8 个字节的 tag hashcode 是否在 SubscriptionData 的 codeSet 中,如果不在就跳过,如果存在把消息返回给 Consumer。如下图:

这样可以在灰度 Producer 发送消息时加上 Tag,如下代码:

Message msg = new Message();
msg.setBody("Test");
msg.setTopic("Topic");
msg.setTags("Gray");

而在灰度消费者订阅 Gray 这个 tag。这样就避免了 2.1 节中消息全量拉取的问题。

2.2.2 使用 SQL92 过滤

使用 SQL92 过滤,可以应对更加复杂的场景,不仅可以过滤 Tag,还可以过滤 UserProperty。

比如下面是一个生产者的代码:

Message msg = new Message();
msg.setTopic("testTopic");
msg.setTags("tag1");
msg.putUserProperty("gray","true");

这样消费者初始化的时候,可以定义使用 SQL92 过滤,代码如下:

consumer.subscribe("testTopic",MessageSelector.bySql("(TAGS is not null and TAGS in TAGS='''''tag1''''')" +"and (gray is not null gray='true')"));

下面是 bySql 的源代码:

public static MessageSelector bySql(String sql) {return new MessageSelector(ExpressionType.SQL92, sql);
}

3 总结

本文介绍了 RocketMQ 灰度消息的使用方法,场景比较简单。对于全链路的复杂灰度场景,可以参考使用阿里的微服引擎 MSE。

面试官:使用 RocketMQ 怎么进行灰度发布?相关推荐

  1. 面试官:RocketMQ是什么,它有什么特性与使用场景?

    文章目录 一.前言 二.面试 三.RocketMQ是什么 四.总结 一.前言 作为一名Java程序员,RocketMQ底层的一些原理是我们不必学会就可以搬砖工作的一种技能点,但是小奇为什么还要讲一下呢 ...

  2. 阿里面试官内部题库,阿里发布2022年Java岗(正式版)面试题

    阿里巴巴2022年Java架构师岗面试题(正式版) 这不马上就是金三银四的面试跳槽季了嘛,小编也是通过一些小手段为大家拿到了一份阿里巴巴2022年Java架构师岗面试题(正式版)现在分享给大家,这份资 ...

  3. 面试官:说说kafka、activemq、rabbitmq、rocketmq都有什么优缺点和使用场景

    为什么使用消息队列?消息队列的优点和缺点?kafka.activemq.rabbitmq.rocketmq都有什么优缺点? 面试官角度分析: (1)你知不知道你们系统里为什么要用消息队列这个东西? ( ...

  4. 面试官再问我如何保证 RocketMQ 不丢失消息,这回我笑了!

    0x00. 消息的发送流程 一条消息从生产到被消费,将会经历三个阶段: 生产阶段,Producer 新建消息,然后通过网络将消息投递给 MQ Broker 存储阶段,消息将会存储在 Broker 端磁 ...

  5. 面试官问发布订阅模式是在问什么?

    大家好,我是若川.最近组织了源码共读活动,感兴趣的可以加我微信 ruochuan12 参与,已进行了三个多月,大家一起交流学习,共同进步. 本文来自 @simonezhou 小姐姐投稿的第八期笔记.面 ...

  6. 阿里发布内部(面试官)题库:2022年Java社招岗(正式版)面试题

    阿里巴巴2022年Java架构师岗面试题(正式版) 这不马上就是金三银四的面试跳槽季了嘛,马士兵老师也是通过一些小手段为大家拿到了一份阿里巴巴2022年Java架构师岗面试题(正式版)现在分享给大家, ...

  7. 魔鬼面试官:用户在电商网站中购买成功了,那么它在微服务中经历了什么?...

    点击上方"朱小厮的博客",选择"设为星标" 做积极的人,而不是积极废人 面试的时候,面试官问:用户在电商网站中购买成功了,那么它在微服务中经历了什么?你该如何作 ...

  8. 灰度发布系统架构设计

    点击上方蓝色"方志朋",选择"设为星标"回复"666"获取独家整理的学习资料! 来源:https://www.toutiao.com/i69 ...

  9. 据说这套组合拳,可以把面试官给问懵逼了,你要不要试试?

    翻译 | Java面试那些事儿 来源 | https://github.com/yifeikong/reverse-interview-zh 下面列表里的问题对于参加技术面试的人来说可能有些用.列表里 ...

最新文章

  1. PHP入门 1 phpstudy安装与配置站点
  2. 找论文太难?试试这款「文本生成」论文搜索工具丨开源
  3. python 基础——变量
  4. 【教程】怎么同时同时ping1000个IP地址?
  5. gcn代码pytorch_GCN的简单实现(pytorch)
  6. 在c 语言中 一个函数由函数头和,C语言程序设计基础教程_习题答案
  7. 报表工具之JasperReports+iReport(1)
  8. QT清空文件夹内所有文件
  9. python画50个图-python 实现在一张图中绘制一个小的子图方法
  10. R 学习笔记《十二》 R语言初学者指南--格包
  11. Linux调试工具之readelf
  12. 修改浏览器的默认最小字号限制(以chrome为例)
  13. 信息安全习题(含答案)
  14. uni-app 省市区选择器
  15. VS2005使用体验
  16. 管理创新——从三个和尚的故事说起
  17. js将文本转成语言播放
  18. 考研数学 - 初数基础整理02
  19. 实操 VM Player和Instant Contiki安装
  20. 监控系统架构设计分层

热门文章

  1. Clubhouse创始人为自己女儿创建了改变世界的社交应用
  2. AR追踪类型与商业应用分析
  3. 模拟黑洞图像_解密真正的黑洞模样!终于不再是模拟照片,这次是玩真的!
  4. 页面链接可以打开但是在扣扣浏览器标题显示404
  5. zookeeper not connected
  6. tt100k数据集跑yolov5s模型时,所遇到的问题记录
  7. VueJS 的VNode
  8. Web Vue VII
  9. ‘XXX’can not be represented as java.sql.Timestamp
  10. 私有云 VS 公有云