什么是TTL :消息的存活时间
什么是死信以及存入死信队列的三种情况
2-1进入死信队列的流程详解
模拟订单服务的延时队列流程
spring 管理自动创建 交换机 队列 并且绑定
/**
* <简述> 容器中的Queue、Exchange、Binding 会自动创建(在RabbitMQ)不存在的情况下
* RabbitMQ中存在 改变Bean中属性也不会变化,需要收到删除MQ中配置
* <详细描述>
* @author syf
* @date 2023/3/13 16:29
* @return null
*/
@Configuration
public class MyRabbitMQConfig {
/**
* 1-创建死信队列(消息过期时间 1分钟)
*
* @return
*/@Bean
public Queue orderDelayQueue() {
/*
Queue(String name, 队列名字
boolean durable, 是否持久化
boolean exclusive, 是否排他
boolean autoDelete, 是否自动删除
Map<String, Object> arguments) 属性
*/
HashMap<String, Object> arguments = new HashMap<>();
arguments.put("x-dead-letter-exchange", "order-event-exchange");//交换机
arguments.put("x-dead-letter-routing-key", "order.release.order");//死信路由
arguments.put("x-message-ttl", 60000); // 消息过期时间 1分钟
Queue queue = new Queue("order.delay.queue", true, false, false, arguments);
return queue;
}
/**
* 2-创建普通队列
*
* @return
*/
@Bean
public Queue orderReleaseQueue() {
Queue queue = new Queue("order.release.order.queue", true, false, false);
return queue;
}
/**
* 3-创建交换机
* @return
*/
@Bean
public Exchange orderEventExchange() {
/*
* String name,
* boolean durable,
* boolean autoDelete,
* Map<String, Object> arguments
* */
return new TopicExchange("order-event-exchange", true, false);
}
/**
* <简述>4- 死信队列绑定交换机
* <详细描述>order.delay.queue 死信队列 和 交换机绑定,路由键为order.create.order
* @author syf
* @date 2023/3/13 16:32
* @return org.springframework.amqp.core.Binding
*/
@Bean
public Binding orderCreateBinding() {
/*
* String destination, 目的地(队列名或者交换机名字)
* DestinationType destinationType, 目的地类型(Queue、Exhcange)
* String exchange, 交换机名称
* String routingKey, 路由键
* Map<String, Object> arguments
* */
return new Binding("order.delay.queue",
Binding.DestinationType.QUEUE,
"order-event-exchange",
"order.create.order",
null);
}
/**
* <简述>5-普通队列绑定交换机
* <详细描述>order.release.order.queue 普通队列 和 交换机绑定,路由键为order.release.order
* @author syf
* @date 2023/3/13 16:33
* @return org.springframework.amqp.core.Binding
*/
@Bean
public Binding orderReleaseBinding() {
return new Binding("order.release.order.queue",
Binding.DestinationType.QUEUE,
"order-event-exchange",
"order.release.order",
null);
}
}
监听消息过期 自动关闭订单。保证最终一致性
**
* <简述>定时关闭订单
* <详细描述> 监听 order.release.order.queue
* @author syf
* @date 2023/3/13 17:03
* @return null
*/
@RabbitListener(queues = "order.release.order.queue")
@Service
public class OrderCloseListener {
@Autowired
private OrderService orderService;
/**
* <简述>
* <详细描述>
* @author syf
* @date 2023/3/13 17:08
* @param orderEntity
* @param channel 通道
* @param message 原生消息
*/
@RabbitHandler
public void listener(OrderEntity orderEntity, Channel channel, Message message) throws IOException {
System.out.println("收到过期的订单信息,准备关闭订单" + orderEntity.getOrderSn());
try {
orderService.closeOrder(orderEntity);
//确收到消息 手动ack
channel.basicAck(message.getMessageProperties().getDeliveryTag(),false);
} catch (Exception e) {
// 解锁失败 将消息重新放回队列,让别人消费
channel.basicReject(message.getMessageProperties().getDeliveryTag(),true);
}
}
}
注意:要设置手动ack,配置类如下
# 手动ack消息,不使用默认的消费端确认
spring.rabbitmq.listener.simple.acknowledge-mode=manual
# RabbitMQ配置
spring.rabbitmq.host=192.168.1.152
spring.rabbitmq.port=5672
# 虚拟主机配置
spring.rabbitmq.virtual-host=/
# 开启发送端消息抵达Broker确认
spring.rabbitmq.publisher-confirms=true
# 开启发送端消息抵达Queue确认
spring.rabbitmq.publisher-returns=true
# 只要消息抵达Queue,就会异步发送优先回调returnfirm
spring.rabbitmq.template.mandatory=true
# 手动ack消息,不使用默认的消费端确认
spring.rabbitmq.listener.simple.acknowledge-mode=manual