RabbitMQ深度探索:死信队列
-
死信队列产生背景:
- RabbitMQ 死信队列俗称 备胎队列:消息中间件因为某种原因拒收该消息后,可以转移到私信队列中存放,死信队列也可以有交换机和路由 key 等
-
生产死信队列的原因:
- 消息投递到 MQ 存放,消息已经过期,消费者没有及时获取到我们的消息,消息如果存放到 MQ 服务器中过期之后,会转移到备胎死信队列存放
- 多列达到最大长度(队列已满)
- 消费者消费多次消息失败,就会转义到私信队列中
-
案例:
- 配置类:
@Component public class DeadExchangeConfig { //普通交换机 @Value("${boyatop.order.exchange}") private String order_exchange; //普通队列 @Value("${boyatop.order.queue}") private String order_queue; //普通队列的 key @Value("${boyatop.order.routingKey}") private String order_rotingKey; //死信交换机 @Value("${boyatop.dlx.exchange}") private String dlx_exchange; //死信队列 @Value("${boyatop.dlx.queue}") private String dlx_queue; //死信队列的 key @Value("${boyatop.dlx.routingKey}") private String dlx_routingKey; //定义死信交换机 @Bean public DirectExchange dlxExchange(){ return new DirectExchange(dlx_exchange); } //定义死信队列 @Bean public Queue dlxQueue(){ return new Queue(dlx_queue); } //定义普通交换机 @Bean public DirectExchange orderExchange(){ return new DirectExchange(order_exchange); } //定义普通队列 @Bean public Queue orderQueue(){ //订单队列绑定死信交换机 Map<String,Object> arguments = new HashMap<>(2); arguments.put("x-dead-letter-exchange",dlx_exchange); arguments.put("x-dead-letter-routing-key",dlx_routingKey); return new Queue(order_queue,true,false,false,arguments); // return QueueBuilder.durable(order_queue).withArguments(arguments).build(); } //订单队列绑定交换机 @Bean public Binding bindingOrderExchange(DirectExchange orderExchange, Queue orderQueue){ return BindingBuilder.bind(orderQueue) .to(orderExchange) .with(order_rotingKey); } //死信队列绑定交换机 @Bean public Binding bindingDlxExchange(DirectExchange dlxExchange, Queue dlxQueue){ return BindingBuilder.bind(dlxQueue).to(dlxExchange).with(dlx_routingKey); } }
- 生产者:
@RestController public class producerService { @Value("${boyatop.order.exchange}") private String orderExchange; @Value("${boyatop.order.routingKey}") private String orderRouTingKey; @Autowired RabbitTemplate rabbitTemplate; @RequestMapping("/sendMsg") public String send(){ String msg = "11111"; rabbitTemplate.convertAndSend(orderExchange,orderRouTingKey,msg,message -> { //设置超时时间 message.getMessageProperties().setExpiration("5000"); return message; }); return "success"; } }
- yml 文件:
spring: rabbitmq: ####连接地址 host: 127.0.0.1 ####端口号 port: 5672 ####账号 username: guest ####密码 password: guest ### 地址 virtual-host: boyatopVirtualHost #演示死信队列 boyatop: #备胎交换机 dlx: exchange: boyatop_dlx_exchange queue: boyatop_dlx_queue routingKey: dlx #普通交换机 order: exchange: boyatop_order_exchange queue: boyatop_order_queue routingKey: order
- 配置类:
-
死信队列架构原理:
- 死信队列和普通队列区别不是很大
- 普通队列和死信队列都有自己独立的交换机、路由 key、队列和消费者
- 区别:
- 生产者投递消息先投递到普通交换机中,普通交换机再将该消息投到普通队列中缓存起来,普通队列对应有自己独立的消费者
- 如果生产者投递消息到普通队列中,普通队列发现该消息一直没有被消费者消费的情况下,这时候会将该消息转移到死信(备胎)交换机中
- 死信(备胎)交换机对应有自己独立的死信(备胎)队列,对应独立的死信(备胎)消费者
-
死信队列应用场景:
- 30 分钟订单超时设计
- redis 过期 key
- 死信延迟队列实现
- 采用死信队列,创建一个普通队列没有对应的消费者消费该消息,在 30 分钟过后就会将该消息转移到死信备胎消费者实现消费
- 死信备胎消费者会根据订单号码查询是否已经支付过,如果没有支付的情况下则会开始回滚库存操作
- 30 分钟订单超时设计