RabbitMQ使用topic Exchange实现微服务分组订阅

案例场景:用户下单后需要多个微服务(如营销、会员)分别订阅并处理订单事件,且每个微服务可能有多个集群实例,需要保证同一个微服务的集群中,只有一个实例消费到消息。

不同于Kafka和rocketMQ有分组消费的功能,rabbitMQ需要通过topic Exchange实现。

1、消息设计

复制代码
{
  "event_type": "order_created",  // 事件类型(如下单、支付成功)
  "order_id": "123456",
  "user_id": "user_789",
  "items": [
    {"product_id": "p1001", "quantity": 2},
    {"product_id": "p1002", "quantity": 1}
  ],
  "total_amount": 399.00,
  "created_at": "2025-07-01T12:00:00Z"
}

2、rabbitMQ设计

使用 topic 类型的 Exchange:支持灵活的路由规则,不同微服务可通过 binding key 订阅特定事件。

Exchange 名称示例:order_events。

复制代码
微服务	    队列名	            绑定键(binding key)
营销系统	    marketing_queue	    order.created.marketing
会员系统	    member_queue	    order.created.member

绑定键规则:<event_type>.<microservice_name>,便于后续扩展(如 order.cancel.marketing)。

3、消息发布

生产者(订单服务)发布消息时,指定路由键(routing key) 为 order.created

java 复制代码
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.ConnectionFactory;
import com.fasterxml.jackson.databind.ObjectMapper;

public class OrderProducer {
    private static final String EXCHANGE_NAME = "order_events";
    private static final String ROUTING_KEY = "order.created";

    public static void main(String[] args) throws Exception {
        // 1. 创建连接
        ConnectionFactory factory = new ConnectionFactory();
        factory.setHost("localhost");
        factory.setUsername("guest");
        factory.setPassword("guest");

        try (Connection connection = factory.newConnection();
             Channel channel = connection.createChannel()) {

            // 2. topic Exchange
            channel.exchangeDeclare(EXCHANGE_NAME, "topic", true);

            // 3. 构造消息
            OrderEvent event = new OrderEvent();
            event.setEvent_type("order_created");
            event.setOrder_id("123456");
            event.setUser_id("user_789");
            event.setItems(List.of(Map.of("product_id", "p1001", "quantity", 2)));
            event.setTotal_amount(399.00);
            event.setCreated_at("2025-07-02T22:00:00Z");

            ObjectMapper mapper = new ObjectMapper();
            String messageJson = mapper.writeValueAsString(event);

            // 4. 发布消息
            channel.basicPublish(
                EXCHANGE_NAME,
                ROUTING_KEY,
                true, // 持久化消息
                new AMQP.BasicProperties.Builder()
                    .deliveryMode(2) // 持久化
                    .build(),
                messageJson.getBytes()
            );

            System.out.println("Sent order event: " + messageJson);
        }
    }
}

4、消息订阅(营销服务)

不同服务只需要修改 QUEUE_NAME 和 BINDING_KEY 就可以了。

java 复制代码
import com.rabbitmq.client.*;
import com.fasterxml.jackson.databind.ObjectMapper;

public class MarketingConsumer {
    private static final String QUEUE_NAME = "marketing_queue";
    private static final String BINDING_KEY = "order.created.marketing";

    public static void main(String[] args) throws Exception {
        ConnectionFactory factory = new ConnectionFactory();
        factory.setHost("localhost");
        factory.setUsername("guest");
        factory.setPassword("guest");

        Connection connection = factory.newConnection();
        Channel channel = connection.createChannel();

        // 1. 声明队列并绑定到 Exchange
        channel.queueDeclare(QUEUE_NAME, true, false, false, null);
        channel.queueBind(QUEUE_NAME, "order_events", BINDING_KEY);

        // 2. 消费者回调
        DeliverCallback deliverCallback = (consumerTag, delivery) -> {
            String messageJson = new String(delivery.getBody(), "UTF-8");
            ObjectMapper mapper = new ObjectMapper();
            OrderEvent event = mapper.readValue(messageJson, OrderEvent.class);

            // 3. 业务逻辑:发送营销短信
            System.out.println("Marketing: Sending SMS for order " + event.getOrder_id());

            // 4. 手动确认消息
            channel.basicAck(delivery.getEnvelope().getDeliveryTag(), false);
        };

        // 5. 设置手动确认
        channel.basicConsume(QUEUE_NAME, false, deliverCallback, consumerTag -> {});
    }
}
相关推荐
ALex_zry1 小时前
Redis Cluster 分布式缓存架构设计与实践
redis·分布式·缓存
为什么不问问神奇的海螺呢丶3 小时前
n9e categraf rabbitmq监控配置
分布式·rabbitmq·ruby
凯子坚持 c3 小时前
C++基于微服务脚手架的视频点播系统---客户端(4)
数据库·c++·微服务
老百姓懂点AI4 小时前
[微服务] Istio流量治理:智能体来了(西南总部)AI调度官的熔断策略与AI agent指挥官的混沌工程
人工智能·微服务·istio
JZC_xiaozhong6 小时前
多系统权限标准不统一?企业如何实现跨平台统一权限管控
java·大数据·微服务·数据集成与应用集成·iam系统·权限治理·统一权限管理
TTBIGDATA7 小时前
【Atlas】Atlas Hook 消费 Kafka 报错:GroupAuthorizationException
hadoop·分布式·kafka·ambari·hdp·linq·ranger
岁岁种桃花儿8 小时前
SpringCloud从入门到上天:Nacos做微服务注册中心
java·spring cloud·微服务
m0_687399849 小时前
telnet localhost 15672 RabbitMQ “Connection refused“ 错误表示目标主机拒绝了连接请求。
分布式·rabbitmq
陌上丨10 小时前
生产环境分布式锁的常见问题和解决方案有哪些?
分布式
新新学长搞科研10 小时前
【智慧城市专题IEEE会议】第六届物联网与智慧城市国际学术会议(IoTSC 2026)
人工智能·分布式·科技·物联网·云计算·智慧城市·学术会议