一、概念
顺序消费可以从业务层次分为两种:全局顺序消息、局部顺序消息
- 全局顺序消息:顾名思义,就是产生消息的顺序和消费消息的顺序一致,比如用户订单,大致分为:创建订单、支付、打包待发货、已发货、用户签收,业务上处理订单时必须按照先后次序来生产、消费消息,不能出现已经消费了支付消息,然后消费创建订单消息
- 局部顺序消息:只要保证同一个订单(相同订单号)生产和消费的先后次序即可
- 保证全局消息顺序方案:创建只有一个message queue的topic,然后生产和消费时只能是单线程,这样就无法高效的处理订单,效率极低。
- 保证局部消息顺序方案:在发送消息时,保证同一业务id(订单ID、用户身份证号、手机号,根据业务场景来定)的消息发送到同一个queue;在消费时,保证同一个queue读取的消息不被并发处理即可,这样同一业务id的消息都是有序的
二、局部消息顺序具体实现
1、pom.xml
springboot、fastjson等依赖包没有粘出来
<dependency>
<groupId>org.apache.rocketmq</groupId>
<artifactId>rocketmq-client</artifactId>
<version>4.4.0</version>
</dependency>
<dependency>
<groupId>org.apache.rocketmq</groupId>
<artifactId>rocketmq-spring-boot-starter</artifactId>
<version>2.0.2</version>
<exclusions>
<exclusion>
<groupId>org.apache.rocketmq</groupId>
<artifactId>rocketmq-client</artifactId>
</exclusion>
<exclusion>
<artifactId>spring-boot-starter-validation</artifactId>
<groupId>org.springframework.boot</groupId>
</exclusion>
<exclusion>
<artifactId>spring-boot-starter</artifactId>
<groupId>org.springframework.boot</groupId>
</exclusion>
</exclusions>
</dependency>
2、订单bean
package com.cn.dl.springbootdemo.bean;
import com.cn.dl.springbootdemo.enums.EnumOrderType;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.io.Serializable;
/**
* Created by yanshao on 2020-05-07.
*/
@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
public class Order implements Serializable {
private static final long serialVersionUID = -6955843080469225187L;
/**
* 订单ID,UUID
* */
private String orderId;
/**
* {@link EnumOrderType#getCode()}
* */
private String orderType;
/**
* {@link EnumOrderType#getDesc()}
* */
private String orderDesc;
}
3、订单类型枚举
package com.cn.dl.springbootdemo.enums;
import lombok.Getter;
/**
* 订单类型
* Created by yanshao on 2020-05-07.
*/
public enum EnumOrderType {
CREATE("01","创建订单"),
PAY("02","支付订单"),
BALE("03","已打包,待发货"),
SEND("04","包裹已发货")
;
@Getter
private String code;
@Getter
private String desc;
EnumOrderType(String code, String desc) {
this.code = code;
this.desc = desc;
}
public static EnumOrderType getByCode(String code){
EnumOrderType[] orderTypes = EnumOrderType.values();
for(EnumOrderType orderType : orderTypes){
if(orderType.getCode().equals(code)){
return orderType;
}
}
return null;
}
}
4、常量参数
package com.cn.dl.springbootdemo.constant;
/**
* Created by yanshao on 2020-05-07.
*/
public class OrderConstant {
public static final String ORDER_TOPIC = "order_msg";
public static final String ORDER_CONSUMER_GROUP = "order_msg_consumer";
}
5、订单消息发送
package com.cn.dl.springbootdemo.mq;
import com.alibaba.fastjson.JSONObject;
import com.cn.dl.springbootdemo.bean.Order;
import com.cn.dl.springbootdemo.constant.OrderConstant;
import org.apache.rocketmq.client.producer.SendResult;
import org.apache.rocketmq.client.producer.SendStatus;
import org.apache.rocketmq.spring.core.RocketMQTemplate;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
/**
* send order message
*/
@Component
public class OrderMessageProducer{
private static final Logger logger = LoggerFactory.getLogger(OrderMessageProducer.class);
@Autowired
private RocketMQTemplate rocketMQTemplate;
/**
* 发送顺序消息,即同一个订单号的消息路由到同一个消息队列
* */
public boolean sendOrderMessage(Order order){
try {
String orderInfo = JSONObject.toJSONString(order);
logger.info("order info :{}",orderInfo);
SendResult sendResult = rocketMQTemplate.syncSendOrderly(OrderConstant.ORDER_TOPIC,orderInfo,order.getOrderId(),3000);
logger.info("orderId: {}, queueId: {}",order.getOrderId(),sendResult.getMessageQueue().getQueueId());
return sendResult.getSendStatus() == SendStatus.SEND_OK;
}catch (Exception e){
logger.error("send message error ",e);
}
return false;
}
/**
* 随机路由到不同消息队列
* */
public boolean randomSendOrderMessage(Order order){
try {
String orderInfo = JSONObject.toJSONString(order);
logger.info("order info :{}",orderInfo);
SendResult sendResult = rocketMQTemplate.syncSend(OrderConstant.ORDER_TOPIC,orderInfo);
logger.info("orderId: {}, queueId: {}",order.getOrderId(),sendResult.getMessageQueue().getQueueId());
return sendResult.getSendStatus() == SendStatus.SEND_OK;
}catch (Exception e){
logger.error("send message error ",e);
}
return false;
}
}
org.apache.rocketmq.spring.core.RocketMQTemplate#syncSendOrderly(java.lang.String, java.lang.Object, java.lang.String, long)
hashKey是传入的订单ID,然后对订单ID计算hashCode值,然后对hashCode取模,返回对应队列。
public SendResult syncSendOrderly(String destination, Object payload, String hashKey, long timeout) {
Message<?> message = this.doConvert(payload, (Map)null, (MessagePostProcessor)null);
return this.syncSendOrderly(destination, message, hashKey, (long)this.producer.getSendMsgTimeout());
}
org.apache.rocketmq.client.producer.selector.SelectMessageQueueByHash#select
public MessageQueue select(List<MessageQueue> mqs, Message msg, Object arg) {
int value = arg.hashCode();
if (value < 0) {
value = Math.abs(value);
}
value %= mqs.size();
return (MessageQueue)mqs.get(value);
}
6、producer测试
package com.cn.dl.springbootdemo.mq;
import com.cn.dl.springbootdemo.bean.Order;
import com.cn.dl.springbootdemo.enums.EnumOrderType;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;
import java.util.UUID;
import java.util.concurrent.TimeUnit;
@RunWith(SpringRunner.class)
@SpringBootTest
public class OrderMessageProducerTest {
private static final Logger logger = LoggerFactory.getLogger(OrderMessageProducerTest.class);
@Autowired
private OrderMessageProducer orderMessageProducer;
@Test
public void sendOrderMessage() throws InterruptedException {
int i = 0;
while (i < 20){
sendOrderMessages();
TimeUnit.MILLISECONDS.sleep(200);
i++;
}
}
@Test
public void randomSendOrderMessage() throws InterruptedException {
int i = 0;
while (i < 2){
randomSendOrderMsg();
TimeUnit.MILLISECONDS.sleep(200);
i++;
}
}
private void sendOrderMessages(){
//The order id is a random UUID
String orderId = UUID.randomUUID().toString().replace("-","");
boolean createMsgSendResult = orderMessageProducer.sendOrderMessage(getOrder(orderId,EnumOrderType.CREATE));
logger.info("Send result[create message]: {}",createMsgSendResult);
boolean payMsgSendResult = orderMessageProducer.sendOrderMessage(getOrder(orderId,EnumOrderType.PAY));
logger.info("Send result[pay message]: {}",payMsgSendResult);
boolean bailMsgSendResult = orderMessageProducer.sendOrderMessage(getOrder(orderId,EnumOrderType.BALE));
logger.info("Send result[bail message]: {}",bailMsgSendResult);
boolean sendMsgSendResult = orderMessageProducer.sendOrderMessage(getOrder(orderId,EnumOrderType.SEND));
logger.info("Send result[send message]: {}",sendMsgSendResult);
}
private void randomSendOrderMsg(){
//The order id is a random UUID
String orderId = UUID.randomUUID().toString().replace("-","");
boolean createMsgSendResult = orderMessageProducer.randomSendOrderMessage(getOrder(orderId,EnumOrderType.CREATE));
logger.info("Send result[create message]: {}",createMsgSendResult);
boolean payMsgSendResult = orderMessageProducer.randomSendOrderMessage(getOrder(orderId,EnumOrderType.PAY));
logger.info("Send result[pay message]: {}",payMsgSendResult);
boolean bailMsgSendResult = orderMessageProducer.randomSendOrderMessage(getOrder(orderId,EnumOrderType.BALE));
logger.info("Send result[bail message]: {}",bailMsgSendResult);
boolean sendMsgSendResult = orderMessageProducer.randomSendOrderMessage(getOrder(orderId,EnumOrderType.SEND));
logger.info("Send result[send message]: {}",sendMsgSendResult);
}
private Order getOrder(String orderId,EnumOrderType orderType){
return Order.builder()
.orderId(orderId)
.orderType(orderType.getCode())
.orderDesc(orderType.getDesc())
.build();
}
}
发送顺序消息,观察message queue的offset以及queueId变化,通过日志发送,同一个订单ID的消息都路由到同一个message queue
15:47:44.515 [main] INFO com.cn.dl.springbootdemo.mq.OrderMessageProducer[27] -order info :{"orderDesc":"创建订单","orderId":"3178a9f4a7504c718c39cca97aab5527","orderType":"01"}
15:47:44.555 [main] INFO com.cn.dl.springbootdemo.mq.OrderMessageProducer[29] -orderId: 3178a9f4a7504c718c39cca97aab5527, queueId: 0
15:47:44.556 [main] INFO com.cn.dl.springbootdemo.mq.OrderMessageProducerTest[40] -Send result[create message]: true
15:47:44.556 [main] INFO com.cn.dl.springbootdemo.mq.OrderMessageProducer[27] -order info :{"orderDesc":"支付订单","orderId":"3178a9f4a7504c718c39cca97aab5527","orderType":"02"}
15:47:44.574 [main] INFO com.cn.dl.springbootdemo.mq.OrderMessageProducer[29] -orderId: 3178a9f4a7504c718c39cca97aab5527, queueId: 0
15:47:44.574 [main] INFO com.cn.dl.springbootdemo.mq.OrderMessageProducerTest[43] -Send result[pay message]: true
15:47:44.574 [main] INFO com.cn.dl.springbootdemo.mq.OrderMessageProducer[27] -order info :{"orderDesc":"已打包,待发货","orderId":"3178a9f4a7504c718c39cca97aab5527","orderType":"03"}
15:47:44.585 [main] INFO com.cn.dl.springbootdemo.mq.OrderMessageProducer[29] -orderId: 3178a9f4a7504c718c39cca97aab5527, queueId: 0
15:47:44.586 [main] INFO com.cn.dl.springbootdemo.mq.OrderMessageProducerTest[46] -Send result[bail message]: true
15:47:44.586 [main] INFO com.cn.dl.springbootdemo.mq.OrderMessageProducer[27] -order info :{"orderDesc":"包裹已发货","orderId":"3178a9f4a7504c718c39cca97aab5527","orderType":"04"}
15:47:44.596 [main] INFO com.cn.dl.springbootdemo.mq.OrderMessageProducer[29] -orderId: 3178a9f4a7504c718c39cca97aab5527, queueId: 0
15:47:44.596 [main] INFO com.cn.dl.springbootdemo.mq.OrderMessageProducerTest[49] -Send result[send message]: true
15:47:44.799 [main] INFO com.cn.dl.springbootdemo.mq.OrderMessageProducer[27] -order info :{"orderDesc":"创建订单","orderId":"43cd12eab881434abae9d5551833ba1e","orderType":"01"}
15:47:44.825 [main] INFO com.cn.dl.springbootdemo.mq.OrderMessageProducer[29] -orderId: 43cd12eab881434abae9d5551833ba1e, queueId: 2
15:47:44.826 [main] INFO com.cn.dl.springbootdemo.mq.OrderMessageProducerTest[40] -Send result[create message]: true
15:47:44.826 [main] INFO com.cn.dl.springbootdemo.mq.OrderMessageProducer[27] -order info :{"orderDesc":"支付订单","orderId":"43cd12eab881434abae9d5551833ba1e","orderType":"02"}
15:47:44.839 [main] INFO com.cn.dl.springbootdemo.mq.OrderMessageProducer[29] -orderId: 43cd12eab881434abae9d5551833ba1e, queueId: 2
15:47:44.839 [main] INFO com.cn.dl.springbootdemo.mq.OrderMessageProducerTest[43] -Send result[pay message]: true
15:47:44.840 [main] INFO com.cn.dl.springbootdemo.mq.OrderMessageProducer[27] -order info :{"orderDesc":"已打包,待发货","orderId":"43cd12eab881434abae9d5551833ba1e","orderType":"03"}
15:47:44.852 [main] INFO com.cn.dl.springbootdemo.mq.OrderMessageProducer[29] -orderId: 43cd12eab881434abae9d5551833ba1e, queueId: 2
15:47:44.852 [main] INFO com.cn.dl.springbootdemo.mq.OrderMessageProducerTest[46] -Send result[bail message]: true
15:47:44.852 [main] INFO com.cn.dl.springbootdemo.mq.OrderMessageProducer[27] -order info :{"orderDesc":"包裹已发货","orderId":"43cd12eab881434abae9d5551833ba1e","orderType":"04"}
15:47:44.863 [main] INFO com.cn.dl.springbootdemo.mq.OrderMessageProducer[29] -orderId: 43cd12eab881434abae9d5551833ba1e, queueId: 2
15:47:44.863 [main] INFO com.cn.dl.springbootdemo.mq.OrderMessageProducerTest[49] -Send result[send message]: true
在rocketmq-console(rocketMq搭建)发现每个queue的offset也是4的倍数
发送非顺序消息,路由到的message queue是随机的
16:06:08.117 [main] INFO com.cn.dl.springbootdemo.mq.OrderMessageProducer[46] -order info :{"orderDesc":"创建订单","orderId":"4994f057936648d4a9de36f9e6d8bb71","orderType":"01"}
16:06:08.239 [main] INFO com.cn.dl.springbootdemo.mq.OrderMessageProducer[48] -orderId: 4994f057936648d4a9de36f9e6d8bb71, queueId: 4
16:06:08.239 [main] INFO com.cn.dl.springbootdemo.mq.OrderMessageProducerTest[68] -Send result[create message]: true
16:06:08.239 [main] INFO com.cn.dl.springbootdemo.mq.OrderMessageProducer[46] -order info :{"orderDesc":"支付订单","orderId":"4994f057936648d4a9de36f9e6d8bb71","orderType":"02"}
16:06:08.252 [main] INFO com.cn.dl.springbootdemo.mq.OrderMessageProducer[48] -orderId: 4994f057936648d4a9de36f9e6d8bb71, queueId: 5
16:06:08.252 [main] INFO com.cn.dl.springbootdemo.mq.OrderMessageProducerTest[71] -Send result[pay message]: true
16:06:08.252 [main] INFO com.cn.dl.springbootdemo.mq.OrderMessageProducer[46] -order info :{"orderDesc":"已打包,待发货","orderId":"4994f057936648d4a9de36f9e6d8bb71","orderType":"03"}
16:06:08.267 [main] INFO com.cn.dl.springbootdemo.mq.OrderMessageProducer[48] -orderId: 4994f057936648d4a9de36f9e6d8bb71, queueId: 6
16:06:08.269 [main] INFO com.cn.dl.springbootdemo.mq.OrderMessageProducerTest[74] -Send result[bail message]: true
16:06:08.270 [main] INFO com.cn.dl.springbootdemo.mq.OrderMessageProducer[46] -order info :{"orderDesc":"包裹已发货","orderId":"4994f057936648d4a9de36f9e6d8bb71","orderType":"04"}
16:06:08.282 [main] INFO com.cn.dl.springbootdemo.mq.OrderMessageProducer[48] -orderId: 4994f057936648d4a9de36f9e6d8bb71, queueId: 7
16:06:08.283 [main] INFO com.cn.dl.springbootdemo.mq.OrderMessageProducerTest[77] -Send result[send message]: true
16:06:08.486 [main] INFO com.cn.dl.springbootdemo.mq.OrderMessageProducer[46] -order info :{"orderDesc":"创建订单","orderId":"7a95c7bfbef043ac82f9d16fe476c0cc","orderType":"01"}
16:06:08.503 [main] INFO com.cn.dl.springbootdemo.mq.OrderMessageProducer[48] -orderId: 7a95c7bfbef043ac82f9d16fe476c0cc, queueId: 0
16:06:08.504 [main] INFO com.cn.dl.springbootdemo.mq.OrderMessageProducerTest[68] -Send result[create message]: true
16:06:08.504 [main] INFO com.cn.dl.springbootdemo.mq.OrderMessageProducer[46] -order info :{"orderDesc":"支付订单","orderId":"7a95c7bfbef043ac82f9d16fe476c0cc","orderType":"02"}
16:06:08.518 [main] INFO com.cn.dl.springbootdemo.mq.OrderMessageProducer[48] -orderId: 7a95c7bfbef043ac82f9d16fe476c0cc, queueId: 1
16:06:08.519 [main] INFO com.cn.dl.springbootdemo.mq.OrderMessageProducerTest[71] -Send result[pay message]: true
16:06:08.520 [main] INFO com.cn.dl.springbootdemo.mq.OrderMessageProducer[46] -order info :{"orderDesc":"已打包,待发货","orderId":"7a95c7bfbef043ac82f9d16fe476c0cc","orderType":"03"}
16:06:08.533 [main] INFO com.cn.dl.springbootdemo.mq.OrderMessageProducer[48] -orderId: 7a95c7bfbef043ac82f9d16fe476c0cc, queueId: 2
16:06:08.535 [main] INFO com.cn.dl.springbootdemo.mq.OrderMessageProducerTest[74] -Send result[bail message]: true
16:06:08.535 [main] INFO com.cn.dl.springbootdemo.mq.OrderMessageProducer[46] -order info :{"orderDesc":"包裹已发货","orderId":"7a95c7bfbef043ac82f9d16fe476c0cc","orderType":"04"}
16:06:08.547 [main] INFO com.cn.dl.springbootdemo.mq.OrderMessageProducer[48] -orderId: 7a95c7bfbef043ac82f9d16fe476c0cc, queueId: 3
16:06:08.547 [main] INFO com.cn.dl.springbootdemo.mq.OrderMessageProducerTest[77] -Send result[send message]: true
7、订单消息消费
package com.cn.dl.springbootdemo.mq;
import com.cn.dl.springbootdemo.constant.OrderConstant;
import org.apache.rocketmq.client.consumer.DefaultMQPushConsumer;
import org.apache.rocketmq.client.consumer.listener.ConsumeOrderlyContext;
import org.apache.rocketmq.client.consumer.listener.ConsumeOrderlyStatus;
import org.apache.rocketmq.client.consumer.listener.MessageListenerOrderly;
import org.apache.rocketmq.common.message.MessageExt;
import org.apache.rocketmq.spring.annotation.ConsumeMode;
import org.apache.rocketmq.spring.annotation.RocketMQMessageListener;
import org.apache.rocketmq.spring.core.RocketMQListener;
import org.apache.rocketmq.spring.core.RocketMQPushConsumerLifecycleListener;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.nio.charset.StandardCharsets;
import java.util.List;
/**
* Created by yanshao on 2020-05-07.
*/
@Component
@RocketMQMessageListener(
topic = OrderConstant.ORDER_TOPIC,
consumerGroup = OrderConstant.ORDER_CONSUMER_GROUP,
consumeMode = ConsumeMode.ORDERLY
)
public class OrderMessageCustomer implements RocketMQListener<MessageExt>, RocketMQPushConsumerLifecycleListener {
private static final Logger logger = LoggerFactory.getLogger(OrderMessageCustomer.class);
@Autowired
private OrderMessageCustomer orderMessageCustomer;
@Override
public void onMessage(MessageExt messageExt) {
String msg = null;
try {
msg = new String(messageExt.getBody(), StandardCharsets.UTF_8.name());
logger.info("order info: {}",msg);
//测试异常情况
throw new RuntimeException();
}catch (Exception e){
logger.warn("consume message error msgId:{} orderInfo:{}",messageExt.getMsgId(),msg,e);
throw new RuntimeException("consumption failure!");
}
}
@Override
public void prepareStart(DefaultMQPushConsumer defaultMQPushConsumer) {
//After failed consumption, the number of retries
defaultMQPushConsumer.setMaxReconsumeTimes(4);
//set the minimum number of consumer threads to 8
defaultMQPushConsumer.setConsumeThreadMin(8);
defaultMQPushConsumer.setMessageListener(new MessageListenerOrderly() {
@Override
public ConsumeOrderlyStatus consumeMessage(List<MessageExt> messageExts, ConsumeOrderlyContext consumeOrderlyContext) {
try {
for(MessageExt messageExt : messageExts){
long now = System.currentTimeMillis();
orderMessageCustomer.onMessage(messageExt);
long costTime = System.currentTimeMillis() - now;
logger.info("consume message threadName:{} msgId: {} costTime: {}",
Thread.currentThread().getName(),messageExt.getMsgId(), costTime);
}
}catch (Exception e){
logger.warn("consume message error",e);
return ConsumeOrderlyStatus.SUSPEND_CURRENT_QUEUE_A_MOMENT;
}
return ConsumeOrderlyStatus.SUCCESS;
}
});
logger.info("start order consumption!");
}
}
prepareStart方法中的逻辑就是消费时给message queue增加了锁,这样保证了每个message queue同一时间有且仅有一个线程在消费
org.apache.rocketmq.spring.support.DefaultRocketMQListenerContainer.DefaultMessageListenerOrderly
8、消费测试
package com.cn.dl.springbootdemo.mq;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;
import java.util.concurrent.TimeUnit;
@RunWith(SpringRunner.class)
@SpringBootTest
public class OrderMessageCustomerTest {
@Test
public void onMessage() throws InterruptedException {
TimeUnit.MINUTES.sleep(10);
}
}
同一时间只有一个线程消费同一订单id的消息
17:23:33.128 [ConsumeMessageThread_4] INFO com.cn.dl.springbootdemo.mq.OrderMessageCustomer[42] -order info: {"orderDesc":"创建订单","orderId":"49b8f4f9b8274036a2eb6b415a1e4622","orderType":"01"}
17:23:33.128 [ConsumeMessageThread_4] INFO com.cn.dl.springbootdemo.mq.OrderMessageCustomer[63] -consume message threadName:ConsumeMessageThread_4 msgId: AC111128823F18B4AAC222A18E7800EC costTime: 0
17:23:33.142 [ConsumeMessageThread_5] INFO com.cn.dl.springbootdemo.mq.OrderMessageCustomer[42] -order info: {"orderDesc":"支付订单","orderId":"49b8f4f9b8274036a2eb6b415a1e4622","orderType":"02"}
17:23:33.142 [ConsumeMessageThread_5] INFO com.cn.dl.springbootdemo.mq.OrderMessageCustomer[63] -consume message threadName:ConsumeMessageThread_5 msgId: AC111128823F18B4AAC222A18E8900EE costTime: 0
17:23:33.153 [ConsumeMessageThread_6] INFO com.cn.dl.springbootdemo.mq.OrderMessageCustomer[42] -order info: {"orderDesc":"已打包,待发货","orderId":"49b8f4f9b8274036a2eb6b415a1e4622","orderType":"03"}
17:23:33.153 [ConsumeMessageThread_6] INFO com.cn.dl.springbootdemo.mq.OrderMessageCustomer[63] -consume message threadName:ConsumeMessageThread_6 msgId: AC111128823F18B4AAC222A18E9500F1 costTime: 0
17:23:33.170 [ConsumeMessageThread_7] INFO com.cn.dl.springbootdemo.mq.OrderMessageCustomer[42] -order info: {"orderDesc":"包裹已发货","orderId":"49b8f4f9b8274036a2eb6b415a1e4622","orderType":"04"}
17:23:33.170 [ConsumeMessageThread_7] INFO com.cn.dl.springbootdemo.mq.OrderMessageCustomer[63] -consume message threadName:ConsumeMessageThread_7 msgId: AC111128823F18B4AAC222A18EA200F4 costTime: 0
17:23:33.912 [ConsumeMessageThread_1] INFO com.cn.dl.springbootdemo.mq.OrderMessageCustomer[42] -order info: {"orderDesc":"创建订单","orderId":"3920dcff817f4e85ac2537d497410262","orderType":"01"}
17:23:33.913 [ConsumeMessageThread_1] INFO com.cn.dl.springbootdemo.mq.OrderMessageCustomer[63] -consume message threadName:ConsumeMessageThread_1 msgId: AC111128823F18B4AAC222A1918C0120 costTime: 1
17:23:33.926 [ConsumeMessageThread_2] INFO com.cn.dl.springbootdemo.mq.OrderMessageCustomer[42] -order info: {"orderDesc":"支付订单","orderId":"3920dcff817f4e85ac2537d497410262","orderType":"02"}
17:23:33.927 [ConsumeMessageThread_2] INFO com.cn.dl.springbootdemo.mq.OrderMessageCustomer[63] -consume message threadName:ConsumeMessageThread_2 msgId: AC111128823F18B4AAC222A191990122 costTime: 0
17:23:33.940 [ConsumeMessageThread_3] INFO com.cn.dl.springbootdemo.mq.OrderMessageCustomer[42] -order info: {"orderDesc":"已打包,待发货","orderId":"3920dcff817f4e85ac2537d497410262","orderType":"03"}
17:23:33.940 [ConsumeMessageThread_3] INFO com.cn.dl.springbootdemo.mq.OrderMessageCustomer[63] -consume message threadName:ConsumeMessageThread_3 msgId: AC111128823F18B4AAC222A191A70125 costTime: 0
17:23:33.950 [ConsumeMessageThread_4] INFO com.cn.dl.springbootdemo.mq.OrderMessageCustomer[42] -order info: {"orderDesc":"包裹已发货","orderId":"3920dcff817f4e85ac2537d497410262","orderType":"04"}
17:23:33.950 [ConsumeMessageThread_4] INFO com.cn.dl.springbootdemo.mq.OrderMessageCustomer[63] -consume message threadName:ConsumeMessageThread_4 msgId: AC111128823F18B4AAC222A191B30128 costTime: 0
处理订单异常情况下,也是按照顺序消息
异常日志比较多,没有贴
ps: 仅仅是demo,可能有bug,对于消息消费consumer类,只是为了验证功能注入了orderMessageCustomer,不应该这样使用,后续补上优化