SpringBoot 中集成RocketMQ
1、依赖与Springboot版本
<properties>
<java.version>17</java.version>
<maven.compiler.source>17</maven.compiler.source>
<maven.compiler.target>17</maven.compiler.target>
<rocketmq.version>5.3.0</rocketmq.version>
<jaeger.version>1.6.0</jaeger.version>
</properties>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>3.0.4</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<dependency>
<groupId>org.apache.rocketmq</groupId>
<artifactId>rocketmq-all</artifactId>
<version>${rocketmq.version}</version>
</dependency>
<dependency>
<groupId>org.apache.rocketmq</groupId>
<artifactId>rocketmq-client</artifactId>
<version>${rocketmq.version}</version>
</dependency>
<dependency>
<groupId>org.apache.rocketmq</groupId>
<artifactId>rocketmq-tools</artifactId>
<version>${rocketmq.version}</version>
</dependency>
<dependency>
<groupId>org.apache.rocketmq</groupId>
<artifactId>rocketmq-acl</artifactId>
<version>${rocketmq.version}</version>
</dependency>
</dependencies>
</dependencyManagement>
<dependencies>
<dependency>
<groupId>org.apache.rocketmq</groupId>
<artifactId>rocketmq-spring-boot-starter</artifactId>
<version>2.3.1</version>
<exclusions>
<exclusion>
<groupId>org.apache.rocketmq</groupId>
<artifactId>rocketmq-client</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.apache.rocketmq</groupId>
<artifactId>rocketmq-client</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.13.2</version>
<scope>test</scope>
</dependency>
</dependencies>
2、配置文件
server: port: 9000 spring: application: name: rocketmq-demo rocketmq: name-server: 192.168.179.128:9876 producer: group: my-test-group send-message-timeout: 3000 retry-times-when-send-failed: 3 retry-times-when-send-async-failed: 3 consumer: # 配置默认的消费者组 group: my-test-consumer-group
3、基础使用介绍
1、普通消息
生产者代码:
@Service public class SimpleProducer { @Autowired private RocketMQTemplate rocketMQTemplate; public void sendMessage(String message) { // 发送普通消息 rocketMQTemplate.convertAndSend("simple-topic", message); System.out.println("发送消息:" + message); } public void sendMessageWithTag(String message, String tag) { // 发送带标签的消息 rocketMQTemplate.convertAndSend("simple-topic:" + tag, message); System.out.println("发送带标签消息:" + message + ", 标签:" + tag); } public void sendMessageWithKey(String message, String key) { // 发送带Key的消息 Message<String> msg = MessageBuilder.withPayload(message).build(); msg.getHeaders().put(MessageConst.PROPERTY_KEYS, key); rocketMQTemplate.send("simple-topic", msg); System.out.println("发送带Key消息:" + message + ", Key:" + key); } }
消费者代码:
@Component
@RocketMQMessageListener(topic = "simple-topic", consumerGroup = "simple-consumer-group")
public class SimpleConsumer implements RocketMQListener<String> {
@Override
public void onMessage(String message) {
System.out.println("接收消息:" + message);
// 处理消息逻辑, 如果业务抛出异常不会自动提交ACK
}
}
2、同步发送、异步发送、单向发送
@Service public class SyncAsyncProducer { @Autowired private RocketMQTemplate rocketMQTemplate; public void sendSyncMessage(String message) { // 同步发送 SendResult sendResult = rocketMQTemplate.syncSend("sync-topic", message); System.out.println("同步发送结果:" + sendResult.getSendStatus()); } public void sendAsyncMessage(String message) { // 异步发送 rocketMQTemplate.asyncSend("async-topic", message, new SendCallback() { @Override public void onSuccess(SendResult sendResult) { System.out.println("异步发送成功:" + sendResult.getSendStatus()); } @Override public void onException(Throwable e) { System.out.println("异步发送失败:" + e.getMessage()); } }); } public void sendOneWayMessage(String message) { // 单向发送(不关心结果) rocketMQTemplate.sendOneWay("oneway-topic", message); System.out.println("单向发送完成"); } }
3、顺序消息
生产者:
@Service public class OrderProducer { @Autowired private RocketMQTemplate rocketMQTemplate; public void sendOrderMessage(String orderId, String message) { // 设置消息队列选择器,确保相同订单的消息发送到同一个队列 SendResult sendResult = rocketMQTemplate.syncSendOrderly( "order-topic", MessageBuilder.withPayload(message).build(), orderId ); System.out.println("发送顺序消息:" + sendResult.getSendStatus()); } }
消息消费者:
@Component @RocketMQMessageListener( topic = "order-topic", consumerGroup = "order-consumer-group", consumeMode = ConsumeMode.ORDERLY ) public class OrderConsumer implements RocketMQListener<String> { @Override public void onMessage(String message) { System.out.println("接收顺序消息:" + message); // 顺序处理消息逻辑 } }
4、延时消息
@Service public class DelayProducer { @Autowired private RocketMQTemplate rocketMQTemplate; public void sendDelayMessage(String message, int delayLevel) { // 方式一 Message<String> msg = MessageBuilder.withPayload(message).build(); // 设置延时等级1-18个延迟级别 msg.getHeaders().put(MessageConst.PROPERTY_DELAY_TIME_LEVEL, String.valueOf(delayLevel)); // RocketMQ5.0+版本支持自定义任意的延迟时间 MessageConst.PROPERTY_TIMER_DELAY_SEC SendResult sendResult = rocketMQTemplate.syncSend("delay-topic", msg); System.out.println("发送延时消息:" + sendResult.getSendStatus()); // 方式二 rocketMQTemplate.syncSend("delay-topic", MessageBuilder.withPayload(message).build(), // 发送超时时间 rocketMQTemplate.getProducer().getSendMsgTimeout(), delayLevel // 直接传入延迟级别 ); } }
5、批量消息
@Service public class BatchProducer { @Autowired private RocketMQTemplate rocketMQTemplate; public void sendBatchMessages(List<String> messages) { // 将消息列表转换为Message列表 List<Message<String>> messageList = messages.stream() .map(msg -> MessageBuilder.withPayload(msg).build()) .collect(Collectors.toList()); // 批量发送 SendResult sendResult = rocketMQTemplate.syncSend("batch-topic", messageList); System.out.println("批量发送结果:" + sendResult.getSendStatus()); } public void sendBatchMessagesWithSplitter(List<String> messages) { // 使用消息分割器处理大批量消息 ListSplitter splitter = new ListSplitter(messages, 1000); // 每批最多1000条 while (splitter.hasNext()) { List<String> batch = splitter.next(); List<Message<String>> messageList = batch.stream() .map(msg -> MessageBuilder.withPayload(msg).build()) .collect(Collectors.toList()); SendResult sendResult = rocketMQTemplate.syncSend("batch-topic", messageList); System.out.println("批量发送结果:" + sendResult.getSendStatus()); } } }
6、事务消息
事务消息确保本地事务和消息发送的原子性。
RocketMQ版本不同,使用上有点区别:@RocketMQTransactionListener 这个注解,有点奇怪。2.0.4版本中,是需要指定txProducerGroup指向一个消息发送者组。但是到了2.1.1版本,只能指定rocketMQTemplateBeanMame属性,也就是说如果你有多个发送者组需要有不同的事务消息逻辑,那就需要定义多个RocketMQTemplate。
2.0.4生产者:
public void sendOrderMessage(Order order) { rocketMQTemplate.sendMessageInTransaction( // 指定消息发送者组 "order-tx-group", "ORDER_TOPIC:create", MessageBuilder.withPayload(order).build(), order ); } public void sendPaymentMessage(Payment payment) { rocketMQTemplate.sendMessageInTransaction( "payment-tx-group", "PAYMENT_TOPIC:process", MessageBuilder.withPayload(payment).build(), payment ); }
2.0.4事务监听:
// 订单事务监听器 @RocketMQTransactionListener(txProducerGroup = "order-tx-group") public class OrderTransactionListenerImpl implements RocketMQLocalTransactionListener { @Autowired private OrderService orderService; @Override public RocketMQLocalTransactionState executeLocalTransaction(Message msg, Object arg) { try { Order order = (Order) arg; boolean success = orderService.createOrder(order); return success ? RocketMQLocalTransactionState.COMMIT : RocketMQLocalTransactionState.ROLLBACK; } catch (Exception e) { return RocketMQLocalTransactionState.ROLLBACK; } } @Override public RocketMQLocalTransactionState checkLocalTransaction(Message msg) { // 检查订单事务状态 return orderService.checkOrderStatus(msg); } } // 支付事务监听器 @RocketMQTransactionListener(txProducerGroup = "payment-tx-group") public class PaymentTransactionListenerImpl implements RocketMQLocalTransactionListener { @Autowired private PaymentService paymentService; @Override public RocketMQLocalTransactionState executeLocalTransaction(Message msg, Object arg) { try { Payment payment = (Payment) arg; boolean success = paymentService.processPayment(payment); return success ? RocketMQLocalTransactionState.COMMIT : RocketMQLocalTransactionState.ROLLBACK; } catch (Exception e) { return RocketMQLocalTransactionState.ROLLBACK; } } @Override public RocketMQLocalTransactionState checkLocalTransaction(Message msg) { // 检查支付事务状态 return paymentService.checkPaymentStatus(msg); } }
2.1.1版本:
@Configuration public class MultiTemplateConfig { /** * 默认消息模板 */ @Bean @Primary public RocketMQTemplate rocketMQTemplate() { return new RocketMQTemplate(); } /** * 订单业务专用模板 */ @Bean("OrderRocketMQTemplate") public RocketMQTemplate orderRocketMQTemplate() { RocketMQTemplate template = new RocketMQTemplate(); // 可以配置订单专用的参数 return template; } /** * 支付业务专用模板 */ @Bean("PaymentRocketMQTemplate") public RocketMQTemplate paymentRocketMQTemplate() { RocketMQTemplate template = new RocketMQTemplate(); // 可以配置支付专用的参数 return template; } } // 订单事务监听器 @RocketMQTransactionListener(rocketMQTemplateBeanName = "OrderRocketMQTemplate") @Service public class OrderTransactionListener implements RocketMQLocalTransactionListener { // 处理订单相关事务消息 } // 支付事务监听器 @RocketMQTransactionListener(rocketMQTemplateBeanName = "PaymentRocketMQTemplate") @Service public class PaymentTransactionListener implements RocketMQLocalTransactionListener { // 处理支付相关事务消息 } @Service public class BusinessService { @Autowired @Qualifier("OrderRocketMQTemplate") private RocketMQTemplate orderRocketMQTemplate; @Autowired @Qualifier("PaymentRocketMQTemplate") private RocketMQTemplate paymentRocketMQTemplate; public void processOrder(Order order) { // 使用订单专用模板 orderRocketMQTemplate.sendMessageInTransaction( "order-group", "ORDER_TOPIC:create", MessageBuilder.withPayload(order).build(), order ); } public void processPayment(Payment payment) { // 使用支付专用模板 paymentRocketMQTemplate.sendMessageInTransaction( "payment-group", "PAYMENT_TOPIC:process", MessageBuilder.withPayload(payment).build(), payment ); } }
也可以使用如下的方式扩展RocketmqTemplate
// 订单业务专用模板 @ExtRocketMQTemplateConfiguration( value = "orderRocketMQTemplate", group = "order-producer-group" ) public class OrderRocketMQTemplateConfig { // 空类即可,注解配置所有参数 } // 支付业务专用模板 @ExtRocketMQTemplateConfiguration( value = "paymentRocketMQTemplate", group = "payment-producer-group" ) public class PaymentRocketMQTemplateConfig { }
7、消息过滤
@Service public class FilterProducer { @Autowired private RocketMQTemplate rocketMQTemplate; public void sendMessageWithUserProperty(String message, String userType) { // 发送带用户属性的消息 Message<String> msg = MessageBuilder.withPayload(message).build(); msg.getHeaders().put("userType", userType); rocketMQTemplate.convertAndSend("filter-topic", msg); System.out.println("发送带属性消息:" + message + ", 用户类型:" + userType); } public void sendMessageWithTag(String message, String tag) { // 发送带标签的消息 rocketMQTemplate.convertAndSend("filter-topic:" + tag, message); System.out.println("发送带标签消息:" + message + ", 标签:" + tag); } }
消费者标签过滤:
@Component @RocketMQMessageListener( topic = "filter-topic", consumerGroup = "filter-consumer-group", selectorExpression = "VIP || SVIP" // 只消费VIP和SVIP标签的消息 ) public class TagFilterConsumer implements RocketMQListener<String> { @Override public void onMessage(String message) { System.out.println("接收过滤消息:" + message); } }
消费者SQL过滤:
@Component @RocketMQMessageListener( topic = "filter-topic", consumerGroup = "sql-filter-consumer-group", selectorType = SelectorType.SQL92, selectorExpression = "userType = 'VIP' AND age > 18" // SQL92表达式过滤 ) public class SqlFilterConsumer implements RocketMQListener<String> { @Override public void onMessage(String message) { System.out.println("接收SQL过滤消息:" + message); } }
4、关于消费失败,消息重试说明
顺序消息机制与普通消息消费失败处理逻辑不一样。

普通消息默认最大重试次数16次,时间间隔从10s--2h, 达到最大重试次数后,消息会进入死信对列,人工干预处理。顺序消息会阻塞当前MessageQueue0后面的消息,如果没有指定最大重试次数,会一直重试,如果手动指定了最大的重试次数,达到最大的重试次数后不会进入重试对列与死信对列,需要我们手动处理达到最大次数后的逻辑。比如记录日志,发送告警等。
@Component @RocketMQMessageListener( topic = "order-topic", consumerGroup = "order-consumer-group", consumeMode = ConsumeMode.ORDERLY, maxReconsumeTimes = 5 ) public class OrderConsumer implements RocketMQListener<MessageExt> { @Override public void onMessage(MessageExt message) { // 顺序处理消息逻辑 try { String messageBody = new String(message.getBody(), StandardCharsets.UTF_8); System.out.println("接收顺序消息内容:" + messageBody); // 处理业务逻辑 boolean success = false; if (!success) { // 达到最大重试次数后,返回 SUSPEND_CURRENT_QUEUE_A_MOMENT 会继续重试 // 需要手动判断重试次数 if (message.getReconsumeTimes() >= 5) { // 手动处理达到最大重试次数的消息(达到最大重试次数后,记录日志、发送邮件等告警) // 确认消费,避免阻塞 return; } throw new RuntimeException("处理业务逻辑异常"); } } catch (Exception e) { System.out.print("顺序消息消费异常"); throw new RuntimeException("处理业务逻辑异常"); } } }

浙公网安备 33010602011771号