How to Implement Gray Release with RocketMQ: Step‑by‑Step Strategies

This article explains how to apply gray release techniques in RocketMQ by upgrading consumers, upgrading producers, and using consumer‑side filtering, tag filtering, and SQL92 filtering, providing concrete code examples, configuration steps, and trade‑off analysis for each approach.

Architect
Architect
Architect
How to Implement Gray Release with RocketMQ: Step‑by‑Step Strategies

Gray Release Overview

Gray release gradually shifts traffic from an old version to a new version, limiting risk in high‑traffic systems. In RPC services this is done by upgrading a single node, monitoring, then proceeding. The same principle can be applied to RocketMQ message flows.

1. Upgrade Only Consumers

If only the consumer logic changes, deploy the new consumer alongside the old one and route a portion of the messages to the new consumer. This mirrors the classic RPC gray‑release pattern.

Consumer upgrade diagram
Consumer upgrade diagram

2. Upgrade Producers as Well

When a producer adds a new field (e.g., createTime in an Order class), consumers must be able to handle the new attribute.

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;
}

2.1 Consumer‑Side Filtering

RocketMQ’s Message class contains a properties map. A custom gray flag can be added when the producer builds the message:

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

A dedicated gray consumer group can filter messages by this flag using a FilterMessageHook:

defaultMQPushConsumerImpl.registerFilterMessageHook(new FilterMessageHook() {
    @Override
    public String hookName() { return "filterHook"; }

    @Override
    public void filterMessage(FilterMessageContext context) {
        List<MessageExt> msgs = context.getMsgList();
        context.setMsgList(msgs.stream()
            .filter(m -> "true".equals(m.getProperty("gray")))
            .collect(Collectors.toList()));
    }
});

Issue: Both the gray and normal consumer groups still pull every message, so the broker and consumer load double.

All consumer groups fetch every message; traffic reduction is only logical, not physical.

The broker serves both groups, increasing its load.

2.2 Broker‑Side Filtering

2.2.1 Tag Filtering

Messages can be tagged (e.g., Gray) and consumers subscribe only to that tag. The broker discards non‑matching tags before returning messages, eliminating the double‑pull problem.

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

2.2.2 SQL92 Filtering

For more complex criteria, RocketMQ supports SQL92‑style selectors that can filter by tags and user properties.

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

Consumers subscribe with a SQL expression:

consumer.subscribe("testTopic",
    MessageSelector.bySql("(TAGS IS NOT NULL AND TAGS IN ('tag1')) " +
        "AND (gray IS NOT NULL AND gray='true')"));

The factory method creates a selector with ExpressionType.SQL92:

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

3. Summary

Three practical gray‑release techniques for RocketMQ are demonstrated:

Upgrade only consumers and route a fraction of messages to the new consumer.

Attach a custom gray flag and filter on the consumer side (noting the double‑pull drawback).

Leverage broker‑side filtering via tags or SQL92 selectors to achieve physical traffic separation.

For end‑to‑end gray deployments spanning multiple services, Alibaba’s Microservice Engine (MSE) can be consulted.

Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

javagray releaseMessage QueueRocketMQSQL92Tag FilteringConsumer Filtering
Architect
Written by

Architect

Professional architect sharing high‑quality architecture insights. Topics include high‑availability, high‑performance, high‑stability architectures, big data, machine learning, Java, system and distributed architecture, AI, and practical large‑scale architecture case studies. Open to ideas‑driven architects who enjoy sharing and learning.

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.