目錄
1.TTL
1.1設置消息的TTL
1.1.1配置交換機&隊列
1.1.2發送消息
?1.1.3運行程序觀察結果
1.2設置隊列的TTL?
1.2.1配置隊列和交換機的綁定關系
1.2.2發送消息
1.2.3運行程序觀察結果
1.3兩者區別
2.死信隊列
2.1 聲名隊列和交換機
2.2正常隊列綁定死信交換機
2.3制造死信產生的條件
2.4 發送消息
2.5測試死信?
?2.6常見面試題
2.6.1死信隊列的概念
2.6.2死信的來源
2.6.3死信隊列的應?場景
1.TTL
1.1設置消息的TTL
目前有兩種方法可以設置消息的TTL
一是設置隊列的TTL,隊列中所有消息都有相同的過期時間,二是對消息本身進行單獨設置,每條消息的TTL可以不同,如果兩種方法一起使用,則消息的TTL以兩者之間較小的那個數值決定。
先看針對每條消息設置TTL
針對每條消息設置TTL的方法是在發送消息的方法中加入expiration的屬性參數,單位為ms
1.1.1配置交換機&隊列
//TTL
public static final String TTL_QUEUE = "ttl_queue";
public static final String TTL_EXCHANGE_NAME = "ttl_exchange";//ttl
//1. 交換機
@Bean("ttlExchange")
public Exchange ttlExchange() {return
ExchangeBuilder.fanoutExchange(Constant.TTL_EXCHANGE_NAME).durable(true).build(
);
}
//2. 隊列
@Bean("ttlQueue")
public Queue ttlQueue() {return QueueBuilder.durable(Constant.TTL_QUEUE).build();
}
//3. 隊列和交換機綁定 Binding
@Bean("ttlBinding")
public Binding ttlBinding(@Qualifier("ttlExchange") FanoutExchange exchange,
@Qualifier("ttlQueue") Queue queue) {return BindingBuilder.bind(queue).to(exchange);
}
1.1.2發送消息
@RequestMapping("/ttl")
public String ttl(){String ttlTime = "10000";//10srabbitTemplate.convertAndSend(Constant.TTL_EXCHANGE_NAME, "", "ttl
test...", messagePostProcessor -> {messagePostProcessor.getMessageProperties().setExpiration(ttlTime);return messagePostProcessor;});return "發送成功!";
}
?1.1.3運行程序觀察結果
發送消息后可以看到Ready數為1
十秒后,刷新頁面發現消息已消失
1.2設置隊列的TTL?
設置隊列的TTL的方法是在創建隊列時,加入x-message-ttl參數實現的,單位是ms
1.2.1配置隊列和交換機的綁定關系
public static final String TTL_QUEUE2 = "ttl_queue2";
//設置ttl
@Bean("ttlQueue2")
public Queue ttlQueue2() {//設置20秒過期return QueueBuilder.durable(Constant.TTL_QUEUE2).ttl(20*1000).build();
}
//3. 隊列和交換機綁定 Binding
@Bean("ttlBinding2")
public Binding ttlBinding2(@Qualifier("ttlExchange") FanoutExchange exchange,
@Qualifier("ttlQueue2") Queue queue) {return BindingBuilder.bind(queue).to(exchange);
}
設置過期時間,也可以采用以下方式:
@Bean("ttlQueue2")
public Queue ttlQueue2() {Map<String, Object> arguments = new HashMap<>();arguments.put("x-message-ttl",20000);//20秒過期return
QueueBuilder.durable(Constant.TTL_QUEUE2).withArguments(arguments).build();
}
1.2.2發送消息
@RequestMapping("/ttl")public String ttl() {
// String ttlTime = "30000";//10s
// //發送帶ttl的消息
// rabbitTemplate.convertAndSend(Constant.TTL_EXCHANGE_NAME, "", "ttl test...", //messagePostProcessor -> {
// messagePostProcessor.getMessageProperties().setExpiration(ttlTime);
// return messagePostProcessor;
// });//發送不帶ttl的消息rabbitTemplate.convertAndSend(Constant.TTL_EXCHANGE_NAME, "", "ttl
test...");return "發送成功!";}
1.2.3運行程序觀察結果
?運行后發現,新增了一個隊列,隊列Features有一個TTL標識
?發送消息后,可以看到Ready消息為1
采?發布訂閱模式, 所有與該交換機綁定的隊列都會收到消息
20s后,刷新頁面,發現消息已經刪除
?
?由于ttl_queue隊列, 未設置過期時間, 所以ttl_queue的消息未刪除。
1.3兩者區別
2.死信隊列
死信(dead message)簡單理解就是因為種種原因無法被消費的信息,就是死信
有死信,自然就有死信隊列。當消息在一個隊列中變成死信之后,它能被重新發送到另一個交換機中,這個交換機就是DLX(Dead Letter Exchange),綁定DLX的隊列,就稱為死信隊列(Dead Letter Queue)簡稱DLQ
消息變成死信主要有以下幾個原因:
1.消息被拒絕(Basic.Reject/Basic.Nack),并且設置requeue參數為false?
2.消息過期
3.隊列達到最大長度
2.1 聲名隊列和交換機
//死信隊列
public static final String DLX_EXCHANGE_NAME = "dlx_exchange";
public static final String DLX_QUEUE = "dlx_queue";
public static final String NORMAL_EXCHANGE_NAME = "normal_exchange";
public static final String NORMAL_QUEUE = “narmal_queue”;
/*** 死信隊列相關配置*/
@Configuration
public class DLXConfig {//死信交換機@Bean("dlxExchange")public Exchange dlxExchange(){return
ExchangeBuilder.topicExchange(Constant.DLX_EXCHANGE_NAME).durable(true).build()
;}//2. 死信隊列@Bean("dlxQueue")public Queue dlxQueue() {return QueueBuilder.durable(Constant.DLX_QUEUE).build();}//3. 死信隊列和交換機綁定 Binding@Bean("dlxBinding")public Binding dlxBinding(@Qualifier("dlxExchange") Exchange exchange,
@Qualifier("dlxQueue") Queue queue) {return BindingBuilder.bind(queue).to(exchange).with("dlx").noargs();}//正常交換機@Bean("normalExchange")public Exchange normalExchange(){return
ExchangeBuilder.topicExchange(Constant.NORMAL_EXCHANGE_NAME).durable(true).buil
d();}//正常隊列@Bean("normalQueue")public Queue normalQueue() {return QueueBuilder.durable(Constant.NORMAL_QUEUE).build();}//正常隊列和交換機綁定 Binding@Bean("normalBinding")public Binding normalBinding(@Qualifier("normalExchange") Exchange
exchange, @Qualifier("normalQueue") Queue queue) {return BindingBuilder.bind(queue).to(exchange).with("normal").noargs();}
}
2.2正常隊列綁定死信交換機
當這個隊列中存在死信時,RabbitMQ會自動的把這個消息重新發布到設置的DLX上,進而被路由到另一個隊列,即死信隊列,可以監聽這個死信隊列中的消息以進行相應的處理
@Bean("normalQueue")
public Queue normalQueue() {Map<String, Object> arguments = new HashMap<>();arguments.put("x-dead-letter-exchange",Constant.DLX_EXCHANGE_NAME);//綁定死信隊列arguments.put("x-dead-letter-routing-key","dlx");//設置發送給死信隊列的
RoutingKeyreturn QueueBuilder.durable(Constant.NORMAL_QUEUE).withArguments(arguments).build();
}
簡寫為
return QueueBuilder.durable(Constant.NORMAL_QUEUE).deadLetterExchange(Constant.DLX_EXCHANGE_NAME).deadLetterRoutingKey("dlx").build();
2.3制造死信產生的條件
@Bean("normalQueue")
public Queue normalQueue() {Map<String, Object> arguments = new HashMap<>();arguments.put("x-dead-letter-exchange",Constant.DLX_EXCHANGE_NAME);//綁定死
信隊列arguments.put("x-dead-letter-routing-key","dlx");//設置發送給死信隊列的
RoutingKey//制造死信產?的條件arguments.put("x-message-ttl",10000);//10秒過期arguments.put("x-max-length",10);//隊列?度return
QueueBuilder.durable(Constant.NORMAL_QUEUE).withArguments(arguments).build();
}
簡寫為:
return QueueBuilder.durable(Constant.NORMAL_QUEUE).deadLetterExchange(Constant.DLX_EXCHANGE_NAME).deadLetterRoutingKey("dlx").ttl(10*1000).maxLength(10L).build();
2.4 發送消息
@RequestMapping("/dlx")public void dlx() {//測試過期時間, 當時間達到TTL, 消息?動進?到死信隊列rabbitTemplate.convertAndSend(Constant.NORMAL_EXCHANGE_NAME, "normal",
"dlx test...");//測試隊列?度
// for (int i = 0; i < 20; i++) {
// rabbitTemplate.convertAndSend(Constant.NORMAL_EXCHANGE_NAME, "normal", "dlx test...");
// }
// //測試消息拒收
// rabbitTemplate.convertAndSend(Constant.NORMAL_EXCHANGE_NAME, "normal", "dlx test...");}
2.5測試死信?
?程序啟動后觀察隊列:

?10s后:
?2.6常見面試題
死信隊列作為RabbitMQ的高級特性,也是面試的一大重點