一.TTL (消息的過期時間)
1.兩種設置方式:
(1)通過隊列屬性設置消息過期時間
所有隊列中的消息超過時間未被消費時,都會過期。
@Bean("ttlQueue")
public Queue queue() {
Map<String, Object> map = new HashMap<String, Object>();
map.put("x-message-ttl", 11000); // 隊列中的消息未被消費 11 秒後過期
return new Queue("GP_TTL_QUEUE", true, false, false, map);
}
(2)設置單條消息的過期時間
@Bean("ttlQueue")
public Queue queue() {
Map<String, Object> map = new HashMap<String, Object>();
map.put("x-message-ttl", 11000); // 隊列中的消息未被消費 11 秒後過期
return new Queue("GP_TTL_QUEUE", true, false, false, map);
}
如果同時指定了 Message TTL 和 Queue TTL,則小的那個時間生效。
二.死信隊列
1.什麼情況下消息會變成死信?
1)消息被消費者拒絕並且未設置重回隊列:(NACK || Reject ) && requeue== false
2)消息過期
3)隊列達到最大長度,超過了最大消息數或字節數,最先入隊的消息會被髮送到死信交換機。
2.死信隊列如何使用?
1)聲 明 死 信 交 換 機 、死 信 隊 列,相互綁定
//死信交換機
@Bean("deatLetterExchange")
public TopicExchange deadLetterExchange() {
return new TopicExchange("GP_DEAD_LETTER_EXCHANGE", true, false, new HashMap<>());
}
@Bean("deatLetterQueue")
public Queue deadLetterQueue() {
return new Queue("GP_DEAD_LETTER_QUEUE", true, false, false, new HashMap<>());
}
@Bean
public Binding bindingDead(@Qualifier("deatLetterQueue") Queue queue,@Qualifier("deatLetterExchange")
TopicExchange exchange) {
return BindingBuilder.bind(queue).to(exchange).with("#"); // 無條件路由
}
2)聲明原交換機、原隊列,相互綁定。隊列中的過期消息,因爲沒有消費者,會變成死信。指定原隊列的死信交換機
//原交換機
@Bean("oriUseExchange")
public DirectExchange exchange() {
return new DirectExchange("GP_ORI_USE_EXCHANGE", true, false, new HashMap<>());
}
@Bean("oriUseQueue")
public Queue queue() {
Map<String, Object> map = new HashMap<String, Object>();
map.put("x-message-ttl", 10000); // 10 秒鐘後成爲死信
map.put("x-dead-letter-exchange", "GP_DEAD_LETTER_EXCHANGE"); // 隊列中的消息變成死信後,進入死信
return new Queue("GP_ORI_USE_QUEUE", true, false, false, map);
}
//綁定
@Bean
public Binding binding(@Qualifier("oriUseQueue") Queue queue,@Qualifier("oriUseExchange") DirectExchange
exchange) {
return BindingBuilder.bind(queue).to(exchange).with("test.ori.use");
}
3)最終消費者監聽死信隊列。
4)生產者發送消息。
三.服務端流控
隊列有兩個控制長度的屬性:x-max-length:隊列中最大存儲最大消息數,超過這個數量,隊頭的消息會被丟棄。x-max-length-bytes:隊列中存儲的最大消息容量,超過這個容量,隊頭的消息會被丟棄。通過設置隊列長度在消息堆積的情況下會刪除先入隊的消息。但如何在消息的產生速度遠大於消費速度的情況下實現服務限流呢。
1.內存控制
RabbitMQ 會在啓動時檢測機器的物理內存數值。默認當 MQ 佔用 40% 以上內存時,MQ 會主動拋出一個內存警告並阻塞所有連接。可以通過修改rabbitmq.config 文件來調整內存閾值,默認值是 0.4,如下所示: {vm_memory_high_watermark, 0.4}。如果設置成0,則所有消息都不能發佈。
2.磁盤控制
通過磁盤來控制消息的發佈。當磁盤空間低於指定的值時(默認50MB),觸發流控措施。
disk_free_limit.relative = 3.0
disk_free_limit.absolute = 2GB