1. 程式人生 > 實用技巧 >RabbitMq高階特性之死信佇列 通俗易懂 超詳細 【內含案例】

RabbitMq高階特性之死信佇列 通俗易懂 超詳細 【內含案例】

RabbitMq高階特性之死信佇列 又稱 死信交換機 DLX

當訊息成為 Dead message 後,會重新發送到另一個交換機,這個交換機就是 DLX

訊息成為死信的情況公有三種:

  1. 佇列訊息長度達到限制
  2. 消費者拒接消費訊息 basicNack/basicReject,並且不把訊息重新放回原目標佇列,requeue=false;
  3. 原佇列訊息存在訊息過期設定,訊息達到過期時間

前提

完成 RabbitMq高階特性之TTL過期設定

一、更改RabbitMqConfig.java檔案

import org.springframework.amqp.core.*;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

/**
 * RabbitMq 配置類
 */
@Configuration
public class RabbitMqConfig {
    private static final String TOPIC_EXCHANGE_NAME = "topic_exchange";
    private static final String TOPIC_QUEUE_NAME = "topic_queue";
    
    public static final String DLX_EXCHANGE = "dlx_exchange";
    public static final String DLX_QUEUE = "dlx_queue";
    public static final String DLX_ROUTING_KEY = "dlx";


    /**
     * 建立 交換機
     * @return
     */
    @Bean
    public Exchange itemTopicExchange(){
        return ExchangeBuilder.topicExchange(TOPIC_EXCHANGE_NAME).build();
    }
    
    @Bean
    public Exchange DlxExchange(){
        return ExchangeBuilder.directExchange(DLX_EXCHANGE).build();
    }

    /**
     * 建立 佇列
     * @return
     */
    @Bean
    public Queue itemQueue(){
        //QueueBuilder.durable(TOPIC_QUEUE_NAME).withArgument("x-message-ttl",3000).build();
        //與下句程式碼 效果一致 寫一個就可以
        //與死信交換機繫結
        return QueueBuilder.durable(TOPIC_QUEUE_NAME).ttl(3000).deadLetterExchange(DLX_EXCHANGE).deadLetterRoutingKey(DLX_ROUTING_KEY).build();
    }
    
    @Bean
    public Queue dlxQueue(){
        return QueueBuilder.durable(DLX_QUEUE).build();
    }

    /**
     * 繫結 交換機與佇列
     * @param exchange
     * @param queue
     * @return
     */
    @Bean
    public Binding itemQueueExchange(@Qualifier("itemTopicExchange") Exchange exchange, @Qualifier("itemQueue") Queue queue){
        return BindingBuilder.bind(queue).to(exchange).with("item.#").noargs();
    }
    
    @Bean
    public Binding itemQueueExchange(@Qualifier("dlxExchange") Exchange exchange, @Qualifier("dlxQueue") Queue queue){
        return BindingBuilder.bind(queue).to(exchange).with(DLX_ROUTING_KEY).noargs();
    }

}

二、測試

  1. 如有topic_queue已存在,請刪除
  2. 執行ProducerTest.java單元測試
  3. 過期的死信佇列會跑到DLX_QUEUE佇列中

三、小結

  1. 死信佇列也可以建立一個消費者來訊息死信訊息
  2. 可以在RabbitMqConfig.java檔案中的itemQueue()方法中設定佇列的最大限度,QueueBuilder.maxLendth(5); 當出入大於5個訊息,多餘的會丟到死信佇列中
  3. channel.basicNack(deliveryTag, true, false);確認訊息但是不傳送回原目標佇列,會丟到死信佇列中