RocketMQ从实战到源码:SpringBoot整合RocketMQ

117 阅读10分钟

RocketMQ从实战到源码:SpringBoot整合RocketMQ

😄生命不息,写作不止

🔥 继续踏上学习之路,学之分享笔记

👊 总有一天我也能像各位大佬一样

🏆 博客首页   @怒放吧德德  To记录领地 @一个有梦有戏的人

🌝分享学习心得,欢迎指正,大家一起学习成长!

转发请携带作者信息  @怒放吧德德(掘金) @一个有梦有戏的人(CSDN)

rocketmq封面.png

前言

在微服务架构中,消息中间件是实现服务解耦、削峰填谷、异步通信的核心组件,而 RocketMQ 作为阿里开源的高性能、高可靠分布式消息中间件,凭借高吞吐量、低延迟、强一致性等特性,广泛应用于各类分布式系统。SpringBoot 则以“约定大于配置”的理念,极大简化了第三方组件的整合成本。本文将从实操角度出发,详细讲解 RocketMQ 与 SpringBoot 的完整整合流程,包含环境准备、依赖配置、生产者/消费者实现、测试验证,以及常见问题排查,适合新手快速上手,也可作为开发参考手册。

1 整合 SpringBoot

1.1 环境

rocketmq: 2.2.3 RocketMQ 与 SpringBoot 的整合依赖官方提供的 starter 组件,版本适配至关重要,否则会出现自动配置失效、Bean 注入失败等问题。本文选用业内稳定兼容版本组合(新手直接照搬即可),版本对应关系参考 Apache RocketMQ 官方兼容性矩阵:

  • JDK:17(需要 1.8+,RocketMQ 对 JDK 11+ 兼容性一般,生产环境优先选用 JDK 8,避免踩坑)
  • SpringBoot:2.7.x(稳定版,避免使用 3.x 版本,与 RocketMQ starter 存在兼容断点)
  • RocketMQ:4.9.7(稳定版,社区长期维护,适配 SpringBoot 2.7.x)
  • RocketMQ SpringBoot Starter:2.2.3(如果使用 2.3 的版本,jdk 需要 17,并且 springboot 需要 3.0 以上)
  • Maven:3.6+(项目构建工具)

1.2 引入依赖

创建 SpringBoot 项目,引入 RocketMQ 整合依赖,核心是 RocketMQ 官方提供的 spring-boot-starter,无需手动引入原生 RocketMQ 客户端依赖,starter 会自动完成依赖管理和自动配置。

<!-- RocketMQ 依赖 -->
<dependency>
    <groupId>org.apache.rocketmq</groupId>
    <artifactId>rocketmq-spring-boot-starter</artifactId>
    <version>2.2.3</version>
</dependency>

1.3 配置

# rocketmq 配置项,对应 RocketMQProperties 配置类
rocketmq:
  name-server: 192.168.109.134:9876 # RocketMQ Namesrv
  # Producer 配置项 (只有配置了生产者,才会初始化RocketMQTemplate)
  producer:
    group: demo-spring-group # 生产者分组(自定义)
    send-message-timeout: 3000 # 发送消息超时时间,单位:毫秒。默认为 3000 。
    compress-message-body-threshold: 4096 # 消息压缩阀值,当消息体的大小超过该阀值后,进行消息压缩。默认为 4 * 1024B
    max-message-size: 4194304 # 消息体的最大允许大小。。默认为 4 * 1024 * 1024B
    retry-times-when-send-failed: 2 # 同步发送消息时,失败重试次数。默认为 2 次。
    retry-times-when-send-async-failed: 2 # 异步发送消息时,失败重试次数。默认为 2 次。
    retry-next-server: false # 发送消息给 Broker 时,如果发送失败,是否重试另外一台 Broker 。默认为 false
    access-key: # Access Key ,可阅读 https://github.com/apache/rocketmq/blob/master/docs/cn/acl/user_guide.md 文档
    secret-key: # Secret Key
    enable-msg-trace: true # 是否开启消息轨迹功能。默认为 true 开启。可阅读 https://github.com/apache/rocketmq/blob/master/docs/cn/msg_trace/user_guide.md 文档
    customized-trace-topic: RMQ_SYS_TRACE_TOPIC # 自定义消息轨迹的 Topic 。默认为 RMQ_SYS_TRACE_TOPIC 。
  # Consumer 配置项 (可以不在这里配置,不在这里配置需要在注解中配置)

启动类不需要配置,就跟使用 redis 一样。

1.4 代码

简单进行操作,做个简单的消费者和生产者进行测试。

构建一个消息类,实际开发中常发送对象消息(如订单信息、用户信息),需创建实体类并实现 Serializable 接口(避免序列化失败)。

public class Demo01Message implements Serializable {
    public static final String TOPIC = "SPRING-DEMO-01";
    private Integer id;
    public Integer getId() {
        return id;
    }
    public void setId(Integer id) {
        this.id = id;
    }
    @Override
    public String toString() {
        return "Demo01Message{" +
        "id=" + id +
        '}';
    }
}

生产者代码

@Component
public class Producer {

    @Autowired
    private RocketMQTemplate rocketMQTemplate;

    /**
     * 同步
     * @param id
     * @return
     */
    public SendResult syncSend(Integer id) {
        // 创建 Demo01Message 消息
        Demo01Message message = new Demo01Message();
        message.setId(id);
        // 同步发送消息
        return rocketMQTemplate.syncSend(Demo01Message.TOPIC, message);
    }

    /**
     * 异步
     * @param id
     * @param callback 回调
     * @return
     */
    public void asyncSend(Integer id, SendCallback callback) {
        // 创建 Demo01Message 消息
        Demo01Message message = new Demo01Message();
        message.setId(id);
        rocketMQTemplate.asyncSend(Demo01Message.TOPIC, message, callback);
    }

    /**
     * 单向发送
     * @param id
     */
    public void onewaySend(Integer id) {
        // 创建 Demo01Message 消息
        Demo01Message message = new Demo01Message();
        message.setId(id);
        rocketMQTemplate.sendOneWay(Demo01Message.TOPIC, message);
    }

}

通过使用 RocketMQTemplate进行发送消息,以上案例测试了 3 种消息发送方式(同步、异步、单向)。

消费者代码

:::info SpringBoot 整合 RocketMQ 后,消费者无需手动启动监听,只需创建一个监听类,实现 RocketMQListener 接口,并用 @RocketMQMessageListener 注解指定订阅的主题和消费者组,Spring 会自动扫描并启动监听。

:::

@Slf4j
@Component
@RocketMQMessageListener(topic = Demo01Message.TOPIC,
        consumerGroup = "GROUP-" + Demo01Message.TOPIC)
public class ConsumerDemo implements RocketMQListener<Demo01Message> {
    @PostConstruct
    public void init() {
        log.info("消费者监听已启动...");
    }
    @Override
    public void onMessage(Demo01Message messageExt) {
        log.info("[消费者][线程号:{} 监听到消息:{}]", Thread.currentThread().getId(), messageExt);
    }
}

注:这个 onMessage 的类型 Demo01Message 可以放原来的类 MessageExt

消费者的声明的所有属性通过@RocketMQMessageListener注解声明,实现 RocketMQListener 接口。

我们构建一个测试类进行擦看测试结果

@Slf4j
@SpringBootTest
class RocketProducerTest {

    @Autowired
    private Producer producer;

    /**
     * 测试同步发送
     */
    @SneakyThrows
    @Test
    void testSyncSend() {
        int id = (int) (System.currentTimeMillis() / 1000);
        SendResult result = producer.syncSend(id);
        log.info("[测试同步发送][发送编号:[{}] 发送结果:[{}]]", id, result);

        // 阻塞等待,保证消费
        new CountDownLatch(1).await();
    }

    @SneakyThrows
    @Test
    void testAsyncSend() {
        int id = (int) (System.currentTimeMillis() / 1000);
        producer.asyncSend(id, new SendCallback() {
            @Override
            public void onSuccess(SendResult sendResult) {
                log.info("[测试异步发送][发送编号:[{}] 发送成功,结果为:[{}]]", id, sendResult);
            }

            @Override
            public void onException(Throwable throwable) {
                log.info("[testASyncSend][发送编号:[{}] 发送异常]]", id, throwable);
            }
        });


        // 阻塞等待,保证消费
        new CountDownLatch(1).await();
    }

    @SneakyThrows
    @Test
    void testOnewaySend() {
        int id = (int) (System.currentTimeMillis() / 1000);

        producer.onewaySend(id);
        log.info("[测试异步发送][发送编号:[{}] 发送成功, 不关心是否被消费!", id);
        // 阻塞等待,保证消费
        new CountDownLatch(1).await();
    }

}

运行结果

更多案例查看 gitee:rocketmq-demo

2 相关配置

结合前文配置文件,补充 RocketMQ 与 SpringBoot 整合的核心配置说明(对应 application.yml),帮助大家根据业务场景灵活调整,避免盲目配置:

配置项含义默认值使用场景
rocketmq.name-serverNameServer 地址,生产者/消费者通过该地址找到 Broker无(必配)单机/集群部署均需配置,集群用分号分隔多个地址
rocketmq.producer.group生产者组名称,同类生产者归为一组无(必配)用于容错和负载均衡,不可与消费者组重名
rocketmq.consumer.group消费者组名称,同类消费者归为一组无(必配)集群模式下分摊消费,广播模式下仅用于标识
rocketmq.consumer.message-model消费模式,CLUSTERING(集群)/BROADCASTING(广播)CLUSTERING集群模式:一条消息仅被组内一个消费者消费;广播模式:组内所有消费者都能收到
rocketmq.producer.retry-times-when-send-failed同步发送失败重试次数(不含第一次发送)2网络波动、Broker 繁忙时,提高消息发送成功率
rocketmq.consumer.consume-message-batch-max-size每次批量消费的消息数量1消息量大时,调大该值提高消费效率(不宜过大,避免内存溢出)

3 常见问题与注意事项(避坑重点)

整合过程中,新手容易遇到各类问题,以下是高频问题及解决方案,结合参考资料中的兼容问题和实操踩坑经验整理:

3.1 常见问题及解决方案

  • 问题1:项目启动失败,提示“Could not autowire. No beans of 'RocketMQTemplate' type found” 解决方案:检查 RocketMQ starter 依赖是否引入,版本是否与 SpringBoot 适配(SpringBoot 2.7.x 对应 starter 2.2.3+);检查配置文件中 rocketmq.name-server 是否配置正确。
  • 问题2:消息发送成功,但消费者收不到消息 解决方案:① 检查生产者和消费者的 topic 是否一致;② 检查消费者组名称是否与 application.yml 中配置的一致;③ 检查消费模式是否正确,集群模式下若多个消费者实例,消息会分摊消费,可关闭其他实例重试;④ 检查 RocketMQ 服务是否正常运行,NameServer 与 Broker 连接是否正常。
  • 问题3:发送对象消息时,消费者接收失败,提示“序列化失败” 解决方案:实体类必须实现 Serializable 接口;确保生产者和消费者的实体类全路径一致(包名、类名完全相同);避免实体类中存在不可序列化的字段(如 transient 修饰的字段)。
  • 问题4:项目启动失败,提示“ApplicationContext 初始化失败” 解决方案:大概率是版本不兼容,SpringBoot 2.7.x 不可使用低于 2.2.3 版本的 RocketMQ starter;避免混合使用不同版本的 Spring 相关依赖。
  • 问题5:消息消费失败,无法触发重试 解决方案:消费方法中若出现异常,需手动抛出 RuntimeException(不可捕获后不抛出),Spring 会感知异常并触发重试;检查重试次数配置(默认16次),重试达到上限后消息会进入死信队列。

3.2 注意事项

  • 版本适配是关键:严格按照本文推荐的版本组合配置,避免因版本不兼容导致各类异常,具体可参考 Apache RocketMQ 官方兼容性矩阵。
  • 组名称规范:生产者组和消费者组不可重名,同一业务场景的生产者/消费者归为同一组,不同业务场景使用不同的组名称。
  • 生产环境配置:生产环境中,需关闭 Broker 的 autoCreateTopicEnable 配置,提前手动创建主题和队列;消息发送失败需做降级处理(如存入数据库,后续补偿发送),避免消息丢失。
  • 消息重试与死信队列:消费失败会触发重试,重试达到上限后消息进入死信队列(DLQ),需手动处理死信队列中的消息,避免数据丢失。
  • 配置文件规范:尽量避免硬编码,消费者组、主题等可通过配置文件读取,方便后续环境切换(开发/测试/生产)。

整合 springboot 是很简单的,使用方法跟 redis 类似,主要是需要了解在什么场景用什么消息发送机制,以及消息发送机制可能会影响的效率。

4 总结

本文详细讲解了 RocketMQ 与 SpringBoot 的完整整合流程,从环境准备、依赖配置、生产者/消费者实现,到测试验证和避坑指南,全程贴合开发实际场景,突出实操性。核心亮点是利用 SpringBoot 的自动配置特性,通过 RocketMQTemplate 和 @RocketMQMessageListener 注解,摒弃了原生 API 繁琐的实例创建和配置,让开发者能够快速实现消息的发送与接收。

整合的核心要点的是“版本适配”和“配置规范”,只要严格遵循本文的版本组合和配置要求,就能顺利完成整合。后续可基于本文的基础,扩展 RocketMQ 的高级功能,如事务消息、延迟消息、消息过滤等,适配更复杂的业务场景(如分布式事务、定时任务通知等)。