RocketMQ在Spring Cloud上的基础使用

12 阅读6分钟

RocketMQ在Spring Cloud上的基础使用

一、整合前置说明

Spring Cloud 整合 RocketMQ 是基于 RocketMQ Spring Boot Starter 扩展,结合 Spring Cloud 生态特性(如配置中心、服务发现、链路追踪)实现云原生、可配置、易扩展的消息通信。

1. 环境依赖

组件版本说明
Spring Cloud2022.0.x(Kilburn)/ Hoxton.SR12适配 Spring Boot 版本
Spring Boot2.7.x / 3.1.x与 Spring Cloud 版本匹配
RocketMQ Spring Boot Starter2.2.3 / 2.3.04.x 用 2.2.3,5.x 用 2.3.0+
RocketMQ4.9.7 / 5.1.4服务端版本需与 Starter 兼容

2. Maven 核心依赖

<!-- Spring Cloud 核心依赖(根据实际生态选择) -->
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter</artifactId>
    <version>2022.0.4</version>
</dependency>

<!-- RocketMQ Spring Boot Starter(核心) -->
<dependency>
    <groupId>org.apache.rocketmq</groupId>
    <artifactId>rocketmq-spring-boot-starter</artifactId>
    <version>2.2.3</version>
</dependency>

<!-- 可选:配置中心(Nacos/Apollo),统一管理 RocketMQ 配置 -->
<dependency>
    <groupId>com.alibaba.cloud</groupId>
    <artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
    <version>2022.0.0.0-RC2</version>
</dependency>

<!-- 可选:链路追踪(SkyWalking/Zipkin) -->
<dependency>
    <groupId>org.apache.skywalking</groupId>
    <artifactId>apm-toolkit-spring-cloud-mvc</artifactId>
    <version>8.16.0</version>
</dependency>

二、核心配置

1. 配置中心统一管理(以 Nacos 为例)

1.1 Nacos 配置文件(rocketmq-config.yaml)
# RocketMQ 核心配置(全局)
rocketmq:
  name-server: ${ROCKETMQ_NAMESRV:127.0.0.1:9876} # 支持环境变量注入
  # 生产者配置
  producer:
    group: ${spring.application.name}-producer # 基于服务名自动生成组名
    send-message-timeout: 5000
    retry-times-when-send-failed: 3
    max-message-size: 4194304
  # 消费者配置
  consumer:
    group: ${spring.application.name}-consumer
    consume-thread-min: 10
    consume-thread-max: 30
    max-reconsume-times: 3
    # 批量消费配置
    consume-message-batch-max-size: 10

# Spring Cloud 扩展配置
spring:
  cloud:
    # 服务注册(可选,与 RocketMQ 无关,仅为微服务规范)
    nacos:
      discovery:
        server-addr: 127.0.0.1:8848
  # 配置中心
  config:
    import:
      - nacos:rocketmq-config.yaml?group=DEFAULT_GROUP&refresh=true # 动态刷新配置
1.2 应用本地配置(bootstrap.yml)
spring:
  application:
    name: rocketmq-cloud-demo # 微服务名称
  profiles:
    active: dev # 环境标识
  cloud:
    nacos:
      config:
        server-addr: 127.0.0.1:8848 # Nacos 配置中心地址
        file-extension: yaml # 配置文件格式
        refresh-enabled: true # 开启配置动态刷新

2. 核心配置项增强说明(Spring Cloud 特性)

配置项Spring Cloud 增强点生产价值
rocketmq.name-server支持环境变量/配置中心动态注入不同环境(dev/test/prod)无需改代码
producer.group基于 ${spring.application.name} 自动生成微服务分组规范,避免手动命名冲突
config.refresh-enabled支持 RocketMQ 配置动态刷新无需重启服务即可调整重试次数、线程数等

三、各消息类型代码示例

1. 普通消息(微服务解耦场景)

1.1 生产者(微服务业务层)
import org.apache.rocketmq.spring.core.RocketMQTemplate;
import org.apache.rocketmq.spring.support.RocketMQHeaders;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.messaging.Message;
import org.springframework.messaging.support.MessageBuilder;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;

/**
 * 订单服务生产者(Spring Cloud 微服务场景)
 * @RefreshScope:支持配置动态刷新
 */
@Component
@RefreshScope
public class OrderNormalProducer {

    @Resource
    private RocketMQTemplate rocketMQTemplate;

    /**
     * 发送订单创建消息(微服务解耦:订单服务 → 库存服务)
     * @param orderId 订单ID
     * @param productId 商品ID
     * @param count 购买数量
     */
    public void sendOrderCreateMsg(String orderId, String productId, Integer count) {
        // 构建业务消息体(JSON 格式,微服务通用)
        OrderMsgDTO msgDTO = OrderMsgDTO.builder()
                .orderId(orderId)
                .productId(productId)
                .count(count)
                .build();

        // 构建 RocketMQ 消息(带微服务链路追踪 Header)
        Message<OrderMsgDTO> message = MessageBuilder
                .withPayload(msgDTO)
                .setHeader(RocketMQHeaders.KEYS, orderId) // 幂等键
                .setHeader(RocketMQHeaders.TAGS, "order_create") // 业务标签
                .setHeader("X-SERVICE-NAME", "order-service") // 微服务标识
                .build();

        // 同步发送(topic:tag 格式,库存服务订阅)
        rocketMQTemplate.syncSend("order_topic:order_create", message);
        System.out.println("[订单服务] 发送普通消息:" + orderId);
    }

    // 业务DTO(微服务通用)
    @lombok.Data
    @lombok.Builder
    public static class OrderMsgDTO {
        private String orderId;
        private String productId;
        private Integer count;
    }
}
1.2 消费者(库存服务)
import org.apache.rocketmq.spring.annotation.ConsumeMode;
import org.apache.rocketmq.spring.annotation.MessageModel;
import org.apache.rocketmq.spring.annotation.RocketMQMessageListener;
import org.apache.rocketmq.spring.core.RocketMQListener;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.stereotype.Component;

/**
 * 库存服务消费者(Spring Cloud 微服务场景)
 * @RefreshScope:配置动态刷新(如消费线程数、重试次数)
 */
@Component
@RefreshScope
@RocketMQMessageListener(
        consumerGroup = "${spring.application.name}-consumer", // 基于服务名自动生成
        topic = "order_topic",
        selectorExpression = "order_create",
        messageModel = MessageModel.CLUSTERING,
        consumeMode = ConsumeMode.CONCURRENTLY,
        maxReconsumeTimes = "${rocketmq.consumer.max-reconsume-times}" // 配置中心注入
)
public class StockNormalConsumer implements RocketMQListener<OrderNormalProducer.OrderMsgDTO> {

    @Override
    public void onMessage(OrderNormalProducer.OrderMsgDTO msg) {
        // 库存扣减业务逻辑(微服务解耦核心)
        System.out.println("[库存服务] 收到订单创建消息:" + msg);
        // 1. 幂等校验(基于 orderId)
        // 2. 扣减库存
        // 3. 记录日志
    }
}

2. 顺序消息(微服务有序业务)

2.1 生产者(物流服务)
import org.apache.rocketmq.spring.core.RocketMQTemplate;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.messaging.support.MessageBuilder;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;

@Component
@RefreshScope
public class LogisticsOrderedProducer {

    @Resource
    private RocketMQTemplate rocketMQTemplate;

    /**
     * 发送物流状态变更消息(保证同一订单的状态顺序)
     * @param orderId 订单ID(hashKey,保证同订单入同队列)
     * @param status 物流状态(已接单→运输中→已送达)
     */
    public void sendLogisticsStatusMsg(String orderId, String status) {
        LogisticsMsgDTO msgDTO = LogisticsMsgDTO.builder()
                .orderId(orderId)
                .status(status)
                .build();

        // 发送顺序消息(hashKey = orderId)
        rocketMQTemplate.syncSendOrderly(
                "logistics_topic:logistics_status",
                MessageBuilder.withPayload(msgDTO).build(),
                orderId // 核心:保证同订单的消息入同一队列
        );
        System.out.println("[物流服务] 发送顺序消息:" + orderId + "-" + status);
    }

    @lombok.Data
    @lombok.Builder
    public static class LogisticsMsgDTO {
        private String orderId;
        private String status;
    }
}
2.2 消费者(订单状态同步服务)
import org.apache.rocketmq.spring.annotation.ConsumeMode;
import org.apache.rocketmq.spring.annotation.RocketMQMessageListener;
import org.apache.rocketmq.spring.core.RocketMQListener;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.stereotype.Component;

@Component
@RefreshScope
@RocketMQMessageListener(
        consumerGroup = "${spring.application.name}-consumer",
        topic = "logistics_topic",
        selectorExpression = "logistics_status",
        consumeMode = ConsumeMode.ORDERLY // 强制顺序消费
)
public class OrderStatusOrderedConsumer implements RocketMQListener<LogisticsOrderedProducer.LogisticsMsgDTO> {

    @Override
    public void onMessage(LogisticsOrderedProducer.LogisticsMsgDTO msg) {
        // 同步订单物流状态(必须顺序执行)
        System.out.println("[订单服务] 收到物流顺序消息:" + msg);
        // 1. 更新订单物流状态
        // 2. 推送用户通知
    }
}

3. 延迟消息(微服务定时任务)

3.1 生产者(订单超时取消)
import org.apache.rocketmq.common.message.Message;
import org.apache.rocketmq.spring.core.RocketMQTemplate;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;

@Component
@RefreshScope
public class OrderDelayProducer {

    @Resource
    private RocketMQTemplate rocketMQTemplate;

    /**
     * 发送订单超时取消延迟消息(15分钟未支付则取消)
     * @param orderId 订单ID
     */
    public void sendOrderTimeoutMsg(String orderId) {
        // 构建延迟消息
        Message rocketMsg = new Message(
                "order_delay_topic",
                "order_timeout",
                orderId.getBytes()
        );
        // 延迟等级10=6分钟,15=20分钟(可从配置中心动态获取)
        int delayLevel = Integer.parseInt(System.getProperty("rocketmq.delay.level", "15"));
        rocketMsg.setDelayTimeLevel(delayLevel);

        // 发送延迟消息
        rocketMQTemplate.getProducer().send(rocketMsg);
        System.out.println("[订单服务] 发送延迟消息:" + orderId + "(延迟等级" + delayLevel + ")");
    }
}
3.2 消费者(订单超时处理)
import org.apache.rocketmq.spring.annotation.RocketMQMessageListener;
import org.apache.rocketmq.spring.core.RocketMQListener;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.stereotype.Component;

@Component
@RefreshScope
@RocketMQMessageListener(
        consumerGroup = "${spring.application.name}-consumer",
        topic = "order_delay_topic",
        selectorExpression = "order_timeout"
)
public class OrderDelayConsumer implements RocketMQListener<String> {

    @Override
    public void onMessage(String orderId) {
        // 订单超时取消逻辑
        System.out.println("[订单服务] 处理超时订单:" + orderId);
        // 1. 查询订单支付状态
        // 2. 未支付则取消订单
        // 3. 恢复库存
    }
}

4. 事务消息(微服务分布式事务)

4.1 事务监听器(核心)
import org.apache.rocketmq.spring.annotation.RocketMQTransactionListener;
import org.apache.rocketmq.spring.core.RocketMQLocalTransactionListener;
import org.apache.rocketmq.spring.core.RocketMQLocalTransactionState;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.messaging.Message;
import org.springframework.stereotype.Component;

/**
 * 支付服务事务监听器(Spring Cloud 微服务分布式事务)
 */
@RefreshScope
@RocketMQTransactionListener(txProducerGroup = "${spring.application.name}-tx-producer")
@Component
public class PayTransactionListener implements RocketMQLocalTransactionListener {

    /**
     * 执行本地事务(支付扣款 + 生成支付记录)
     */
    @Override
    public RocketMQLocalTransactionState executeLocalTransaction(Message msg, Object arg) {
        String orderId = msg.getHeaders().get("KEYS").toString();
        try {
            // 1. 调用支付接口扣款(微服务内部调用)
            boolean paySuccess = payService.deductBalance(orderId);
            // 2. 生成支付记录(本地数据库操作)
            boolean recordSuccess = payRecordService.createRecord(orderId);
            
            if (paySuccess && recordSuccess) {
                return RocketMQLocalTransactionState.COMMIT;
            } else {
                return RocketMQLocalTransactionState.ROLLBACK;
            }
        } catch (Exception e) {
            // 未知状态,等待回查
            return RocketMQLocalTransactionState.UNKNOWN;
        }
    }

    /**
     * 事务回查(Broker 主动调用,微服务需提供查询接口)
     */
    @Override
    public RocketMQLocalTransactionState checkLocalTransaction(Message msg) {
        String orderId = msg.getHeaders().get("KEYS").toString();
        // 查询本地事务状态(微服务内部查询)
        boolean isSuccess = payRecordService.queryPayStatus(orderId);
        return isSuccess ? RocketMQLocalTransactionState.COMMIT : RocketMQLocalTransactionState.ROLLBACK;
    }

    // 注入微服务业务层(示例)
    @Resource
    private PayService payService;
    @Resource
    private PayRecordService payRecordService;
}
4.2 事务生产者(支付服务)
import org.apache.rocketmq.spring.core.RocketMQTemplate;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.messaging.Message;
import org.springframework.messaging.support.MessageBuilder;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;

@Component
@RefreshScope
public class PayTransactionProducer {

    @Resource
    private RocketMQTemplate rocketMQTemplate;

    /**
     * 发送支付成功事务消息(通知订单服务更新状态)
     * @param orderId 订单ID
     * @param payAmount 支付金额
     */
    public void sendPaySuccessMsg(String orderId, Double payAmount) {
        PayMsgDTO msgDTO = PayMsgDTO.builder()
                .orderId(orderId)
                .payAmount(payAmount)
                .build();

        Message<PayMsgDTO> message = MessageBuilder
                .withPayload(msgDTO)
                .setHeader("KEYS", orderId)
                .setHeader("TAGS", "pay_success")
                .build();

        // 发送事务消息(Spring Cloud 微服务分布式事务核心)
        rocketMQTemplate.sendMessageInTransaction(
                "pay_topic:pay_success",
                message,
                null
        );
        System.out.println("[支付服务] 发送事务消息(半消息):" + orderId);
    }

    @lombok.Data
    @lombok.Builder
    public static class PayMsgDTO {
        private String orderId;
        private Double payAmount;
    }
}

5. 批量消息(微服务批量处理)

5.1 生产者(日志收集服务)
import org.apache.rocketmq.common.message.Message;
import org.apache.rocketmq.spring.core.RocketMQTemplate;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;

@Component
@RefreshScope
public class LogBatchProducer {

    @Resource
    private RocketMQTemplate rocketMQTemplate;

    /**
     * 批量发送微服务日志(提升吞吐,减少网络开销)
     * @param logList 日志列表
     */
    public void sendLogBatchMsg(List<LogDTO> logList) {
        List<Message> msgList = new ArrayList<>();
        for (LogDTO log : logList) {
            Message msg = new Message(
                    "log_topic",
                    "service_log",
                    log.getLogId().getBytes(),
                    log.toString().getBytes()
            );
            msgList.add(msg);
        }

        // 发送批量消息
        rocketMQTemplate.getProducer().send(msgList);
        System.out.println("[日志服务] 发送批量日志消息:" + logList.size() + "条");
    }

    @lombok.Data
    public static class LogDTO {
        private String logId;
        private String serviceName;
        private String content;
        private Long timestamp;
    }
}
5.2 批量消费者(日志分析服务)
import org.apache.rocketmq.spring.annotation.RocketMQMessageListener;
import org.apache.rocketmq.spring.core.RocketMQBatchListener;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.stereotype.Component;

import java.util.List;

@Component
@RefreshScope
@RocketMQMessageListener(
        consumerGroup = "${spring.application.name}-consumer",
        topic = "log_topic",
        selectorExpression = "service_log",
        consumeMessageBatchMaxSize = "${rocketmq.consumer.consume-message-batch-max-size}"
)
public class LogBatchConsumer implements RocketMQBatchListener<String> {

    @Override
    public void onMessage(List<String> msgs) {
        // 批量分析日志(微服务日志聚合)
        System.out.println("[日志分析服务] 收到批量日志:" + msgs.size() + "条");
        // 1. 解析日志内容
        // 2. 统计服务调用次数
        // 3. 写入 Elasticsearch
    }
}

四、Spring Cloud 整合 RocketMQ 的优缺点

优点(核心价值)

优势详细说明微服务场景价值
配置统一管理结合 Nacos/Apollo 配置中心,实现 RocketMQ 配置动态注入、刷新不同环境(dev/test/prod)无需改代码,配置可灰度发布
微服务解耦替代 RPC 直连,通过消息实现微服务异步通信,降低服务依赖订单、库存、支付服务解耦,单个服务故障不影响整体
服务治理整合可结合 Spring Cloud 链路追踪(SkyWalking)、监控(Prometheus)全链路追踪消息收发,监控消息堆积、消费延迟
动态扩缩容消费者组支持微服务实例动态扩缩容,自动负载均衡秒杀场景可快速扩容消费者实例,应对流量峰值
命名规范统一基于 ${spring.application.name} 自动生成生产者/消费者组名避免人工命名冲突,符合微服务命名规范
配置动态刷新通过 @RefreshScope 实现 RocketMQ 配置热更新无需重启服务即可调整重试次数、线程数等参数
分布式事务适配事务消息结合微服务本地事务,实现最终一致性解决支付、订单等场景的分布式事务问题

缺点(注意事项)

问题详细说明解决方案
依赖复杂度提升引入 Spring Cloud + RocketMQ 双重依赖,版本兼容问题突出严格按照版本适配表选择依赖,避免跨版本使用
运维成本增加需同时维护 RocketMQ 集群 + Spring Cloud 配置中心/注册中心标准化部署流程,统一监控 RocketMQ 和微服务
配置优先级问题Spring Cloud 配置中心、本地配置、环境变量优先级易混乱明确配置优先级(配置中心 > 环境变量 > 本地配置)
链路追踪复杂消息跨微服务传递时,链路追踪需手动传递 Header使用 RocketMQ Headers 传递 traceId,集成 SkyWalking
动态配置风险错误的动态配置(如重试次数改为0)可能导致业务异常配置修改前做灰度验证,增加配置校验规则
消费堆积排查难微服务集群下,消费堆积需定位到具体实例结合 RocketMQ Dashboard + 微服务监控,定位堆积实例
事务回查复杂度微服务事务回查需提供跨服务查询接口,增加开发成本封装通用事务回查组件,统一回查逻辑

五、生产级最佳实践

1. 配置管理

  • 所有 RocketMQ 配置放入配置中心,避免硬编码;
  • 配置按环境分组(dev/test/prod),通过 spring.profiles.active 切换;
  • 关键配置(如 max-reconsume-times)增加修改审批流程。

2. 链路追踪

  • 在消息 Header 中传递 traceId/spanId,集成 SkyWalking/Zipkin;
  • 日志中打印 msgKey + traceId,便于问题定位。

3. 监控告警

  • 监控指标:消息堆积量、发送/消费失败率、延迟时间、选举次数(Dledger);
  • 告警规则:堆积量 > 10000 触发告警,消费失败率 > 1% 触发告警。

4. 幂等性保障

  • 所有消费端基于 msgKey 做幂等(Redis 分布式锁/数据库唯一键);
  • 避免因重试导致重复处理业务。

5. 故障演练

  • 定期演练 Leader 宕机、网络分区、消费堆积等场景;
  • 验证 Spring Cloud 配置动态刷新、微服务扩缩容的有效性。

总结

核心关键点

  1. 整合核心:Spring Cloud 整合 RocketMQ 本质是「RocketMQ Spring Boot Starter + 微服务生态增强」,核心价值是配置统一管理、服务解耦、动态扩缩容;
  2. 优缺点平衡:优势在于微服务解耦和配置灵活性,缺点是依赖复杂度和运维成本增加,需通过标准化流程规避;
  3. 消息类型适配
    • 普通消息:微服务异步解耦首选;
    • 顺序消息:物流、订单状态同步等有序业务;
    • 延迟消息:订单超时、定时任务等场景;
    • 事务消息:支付、库存等分布式事务场景;
    • 批量消息:日志收集、数据同步等吞吐敏感场景;
  4. 生产准则:配置统一管理、链路全追踪、消费必幂等、监控全覆盖。