RabbitMQ死信队列

在这里插入图片描述

什么是死信?

当一条消息出现以下情况,即可称为死信:

  • 消息被拒绝(basicNack/basicReject),同时消息不能重写进入队列(requeue=false)
  • 消息 x-message-ttl 过期
  • 队列达到最大长度,消息

什么是死信队列?

消费死信消息的队列(通过死信交换机,死信队列对死信消息进行路由,消费)

死信队列可以做什么?

  • 如订单支付超时取消问题
  • 延时处理问题
  • 防止消息堆积

死信队列如何实现?

  1. 创建工作交换机,工作队列,绑定关系
  2. 创建工作队列对应的死信交换机,死信队列,绑定关系
  3. 绑定工作队列与死信队列,设置工作队列的TTL
  4. 创建工作队列的监听
  5. 创建死信队列的监听

消息队列全局配置

spring:
  rabbitmq:
    host: localhost
    port: 5671
    username: gg
    password: gg
    listener:
      direct:
        acknowledge-mode: manual
      simple:
        acknowledge-mode: manual
    publisher-confirms: true
    cache:
      channel:
        size: 100
      connection:
        size: 100
        mode: connection
    template:
      retry:
        enabled: true
        max-attempts: 10

创建工作队列,死信队列并绑定对应关系

/**
 * 死信队列,延时队列创建
 * @author flj
 */
@Configuration
public class RabbitmqConfig {
    /******************************************公有配置***************************************/
    
    /**
     * 绑定死信交换机key(绑定死信队列固定参数)
     */
    private final String xDeadLetterExchange = "x-dead-letter-exchange";
    /**
     * 绑定死信路由key(绑定死信队列固定参数)
     */
    private final String xDeadLetterRoutingKey = "x-dead-letter-routing-key";
    /**
     * 超时时间(配置延时队列固定参数)
     */
    private final String xMessageTtl = "x-message-ttl";
    
    /******************************************* 业务配置*********************************** */
    /**
     * 业务交换机
     */
    public static final String WORK_EXCHANGE = "work_exchange";
    /**
     * 业务routing_key
     */
    public static final String WORK_ROUTING_KEY = "work_routing_key";
    /**
     * 死信交换机
     */
    public static final String DEAD_LETTER_EXCHANGE= "dead_letter_exchange";
    /**
     * 死信路由
     */
    public static final String DEAD_LETTER_ROUTING_KEY = "dead_routing_key";
    /**
     * 死信队列
     */
    public static final String DEAD_LETTER_QUEUE = "dead_letter_queue";

    /*****************************************创建死信交换机,死信队列,绑定关系************************/

    /**
     * 创建死信交换机
     */
    @Bean("deadLetterExchange")
    public DirectExchange deadLetterExchange(){
        return new DirectExchange(DEAD_LETTER_EXCHANGE);
    }

    /**
     * 创建死信队列
     */
    @Bean("deadLetterQueue")
    public Queue deadLetterQueue(){
        return new Queue(DEAD_LETTER_QUEUE);
    }

    /**
     * 死信队列,绑定死信交换机,死信路由
     * @param queue 死信队列
     * @param exchange 绑定死信交换机
     * @return Binding
     */
    @Bean
    public Binding deadBinding(@Qualifier("deadLetterQueue") Queue queue, @Qualifier("deadLetterExchange") DirectExchange exchange){
        return  BindingBuilder.bind(queue).to(exchange).with(DEAD_LETTER_ROUTING_KEY);
    }

    /*****************************************创建工作交换机,工作队列(绑定死信队列),绑定关系****************************/
    
    /**
     * 创建第三方交换机
     * @return
     */
    @Bean("workExchange")
    public DirectExchange workExchange(){
        return new DirectExchange(WORK_EXCHANGE);
    }

    /**
     * 创建三方工单队列
     * 绑定死信交换机key: x-dead-letter-exchange
     * 绑定死信路由key: x-dead-letter-routing-key
     * @return
     */
    @Bean("workQueue")
    public Queue workQueue(){
        Map<String, Object> args = new HashMap<>(3);
        args.put(xDeadLetterExchange, DEAD_LETTER_EXCHANGE);
        args.put(xDeadLetterRoutingKey, DEAD_LETTER_ROUTING_KEY);
        args.put(xMessageTtl, 60000);
        return QueueBuilder.durable(WORK_QUEUE).withArguments(args).build();
    }

    /**
     * 绑定队列,交换机,路由
     * @param queue 队列
     * @param exchange 交换机
     * @return Binding
     */
    @Bean
    public Binding workBinding(@Qualifier("workQueue") Queue queue, @Qualifier("workExchange") DirectExchange exchange){
        return BindingBuilder.bind(queue).to(exchange).with(WORK_ROUTING_KEY);
    }

}

创建消息监听

/**
 * 消息消费
 * @author flj
 */
@Slf4j
@Component
public class WorkQueueConsumer {
    
    /**
     * 监听工作队列
     * @param message 消息
     * @param channel 通道
     * @throws Exception
     */
    @RabbitListener(queues = RabbitmqConfig.WORK_QUEUE)
    public void messageConsumer(Message message, Channel channel) throws Exception{
        log.debug("打印接收消息{}", new String(message.getBody()));
        // 拒绝当前消息,进入绑定的死信队列
        // 参数1:消息标签;参数2:仅拒绝当前消息;参数3:不重新进入队列
        channel.basicNack(message.getMessageProperties().getDeliveryTag(), false,false);
    }

    /**
     * 监听与工作队列绑定的死信队列
     * @param message 消息
     * @param channel 通道
     * @throws IOException
     */
    @RabbitListener(queues = RabbitmqConfig.DEAD_LETTER_QUEUE)
    public void deadLetterQueueHandle(Message message, Channel channel) throws IOException {
        log.debug("打印死信消息{}", new String(message.getBody()));
        // 手动消息确认
        channel.basicAck(message.getMessageProperties().getDeliveryTag(), false);
    }
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值