一張圖帶你理解和實現RabbitMQ的延遲佇列功能
開頭
先熟悉下面會用到的一些名詞~
exchange: 交換機
routingkey: 路由key
queue: 佇列
exchange和queue是需要繫結在一起的,然後訊息傳送到exchange再由exchange通過routingkey傳送到對應的佇列中。
(不是這張圖~~~)
exchange分四種
Default Exchange
這種是特殊的Direct Exchange,是rabbitmq內部預設的一個交換機。該交換機的name是空字串,所有queue都預設binding 到該交換機上。所有binding到該交換機上的queue,routing-key都和queue的name一樣。
注意: 這就是為什麼你直接建立一個queue也能正常的生產與消費,因為對應的exchange是RabbitMQ預設的,routingkey就是該佇列的名字
Topic Exchange
萬用字元交換機,exchange會把訊息傳送到一個或者多個滿足萬用字元規則的routing-key的queue。其中表號匹配一個word,#匹配多個word和路徑,路徑之間通過.隔開。如滿足a..c的routing-key有a.hello.c;滿足#.hello的routing-key有a.b.c.helo。
Fanout Exchange
扇形交換機,該交換機會把訊息傳送到所有binding到該交換機上的queue。這種是publisher/subcribe模式。用來做廣播最好。
所有該exchagne上指定的routing-key都會被ignore掉。
Header Exchange
設定header attribute引數型別的交換機。
簡單的瞭解之後,下面就是延遲佇列的實現方式
延遲佇列的實現
延遲分兩種
- 在msg上設定過期時間
- 在佇列上設定過期時間
如上圖建立三個exchange和三個佇列
@Bean
public DirectExchange delayExchange() {
return new DirectExchange(DELAY_EXCHANGE_NAME);
}
@Bean
public DirectExchange processExchange() {
return new DirectExchange(PROCESS_EXCHANGE_NAME);
}
@Bean
public DirectExchange delayQueueExchange() {
return new DirectExchange(DELAY_QUEUE_EXCHANGE_NAME);
}
/**
* 存放延遲訊息的佇列 最後將會轉發給exchange(實際消費佇列對應的)
* @return
*/
@Bean
Queue delayQueue4Msg(){
return QueueBuilder.durable(DELAY_QUEUE_MSG)
.withArgument("x-dead-letter-exchange", PROCESS_EXCHANGE_NAME)
.withArgument("x-dead-letter-routing-key", ROUTING_KEY)
.build();
}
@Bean
public Queue processQueue() {
return QueueBuilder.durable(PROCESS_QUEUE)
.build();
}
/**
* 存放訊息的延遲佇列 最後將會轉發給exchange(實際消費佇列對應的)
* @return
*/
@Bean
public Queue delayQueue4Queue() {
return QueueBuilder.durable(DELAY_QUEUE_NAME)
.withArgument("x-dead-letter-exchange", PROCESS_EXCHANGE_NAME) // DLX
.withArgument("x-dead-letter-routing-key", ROUTING_KEY)
.withArgument("x-message-ttl", 3000) // 設定佇列的過期時間 單位毫秒
.build();
}
接下來將每個exchange和對應的mq繫結
@Bean
Binding delayBinding() {
return BindingBuilder.bind(delayQueue4Msg())
.to(delayExchange())
.with(ROUTING_KEY);
}
@Bean
Binding queueBinding() {
return BindingBuilder.bind(processQueue())
.to(processExchange())
.with(ROUTING_KEY);
}
@Bean
Binding delayQueueBind() {
return BindingBuilder.bind(delayQueue4Queue())
.to(delayQueueExchange())
.with(ROUTING_KEY);
}
傳送訊息的方式
public void sendDelayMsg(Msg msg) {
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
System.out.println(msg.getId() + " 延遲訊息傳送時間:" + sdf.format(new Date()));
rabbitTemplate.convertAndSend(RabbitConfig.DELAY_EXCHANGE_NAME, "delay", msg, new MessagePostProcessor() {
@Override
public Message postProcessMessage(Message message) throws AmqpException {
message.getMessageProperties().setExpiration(msg.getTtl() + "");
return message;
}
});
}
public void sendDelayQueue(Msg msg) {
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
System.out.println(msg.getId() + " 延遲佇列訊息傳送時間:" + sdf.format(new Date()));
rabbitTemplate.convertAndSend(RabbitConfig.DELAY_QUEUE_EXCHANGE_NAME,"delay", msg);
}
驗證結果
如果你把設定了過期時間的訊息傳送到設定了過期時間的隊裡中的時候,以最短的時間為準~~
最後
其實我在實現的過程中也花了很長的時間,主要就是被exchange和queue搞亂掉了,最後索性自己畫了個圖,按照圖來一個一個建立與繫結。之後就很清晰很容易的實現了。
強調!!! 如果在開發的過程中發現exchange和queue繫結錯誤了,建議從管理介面將queue和exchange unbind或者刪除重新建立!
程式碼已上傳到Github上Here
CSDN:http://blog.csdn.net/qqhjqs?viewmode=list
簡書:https://www.jianshu.com/u/223a1314e818
Github:https://github.com/vector4wang
Gitee:https://gitee.com/backwxc
如果感覺有幫助的話,點個贊哦~
相關文章
- 【RabbitMQ】一文帶你搞定RabbitMQ延遲佇列MQ佇列
- RabbitMQ實現延遲佇列MQ佇列
- RabbitMQ 實現延遲佇列MQ佇列
- Golang 實現 RabbitMQ 的延遲佇列GolangMQ佇列
- 如何用RabbitMQ實現延遲佇列MQ佇列
- RabbitMQ、RocketMQ、Kafka延遲佇列實現MQKafka佇列
- RabbitMQ實戰《延遲佇列》MQ佇列
- 實現簡單延遲佇列和分散式延遲佇列佇列分散式
- Delayed Message 外掛實現 RabbitMQ 延遲佇列MQ佇列
- 基於訊息佇列(RabbitMQ)實現延遲任務佇列MQ
- 你知道Redis可以實現延遲佇列嗎?Redis佇列
- RabbitMQ 學習筆記 -- 12 死信佇列 DLX + TTL 方式實現延遲佇列MQ筆記佇列
- 詳細介紹Spring Boot + RabbitMQ實現延遲佇列Spring BootMQ佇列
- Spring Boot(十四)RabbitMQ延遲佇列Spring BootMQ佇列
- 使用 RabbitMQ 實現延時佇列MQ佇列
- 你真的知道怎麼實現一個延遲佇列嗎?佇列
- php+redis實現延遲佇列PHPRedis佇列
- 如何才能讓Spring Boot與RabbitMQ結合實現延遲佇列Spring BootMQ佇列
- Node.js結合RabbitMQ延遲佇列實現定時任務Node.jsMQ佇列
- Laravel 延遲佇列Laravel佇列
- redis 延遲佇列Redis佇列
- 延時佇列(RabbitMQ)佇列MQ
- 高可用延遲佇列設計與實現佇列
- RabbitMQ 延遲佇列實現訂單支付結果非同步階梯性通知MQ佇列非同步
- RabbitMQ使用 prefetch_count優化佇列的消費,使用死信佇列和延遲佇列實現訊息的定時重試,golang版本MQ優化佇列Golang
- RabbitMQ延時佇列的使用MQ佇列
- 延遲阻塞佇列 DelayQueue佇列
- hyperf redis延遲佇列Redis佇列
- RabbitMQ:偽延時佇列MQ佇列
- 帶你玩轉RabbitMQ的五種佇列MQ佇列
- 訊息佇列-一篇讀懂rabbitmq(生命週期,confirm模式,延遲佇列,叢集)佇列MQ模式
- 基於rabbitmq延遲外掛實現分散式延遲任務MQ分散式
- Laravel 在事件監聽中實現佇列的方法以及指定加入的佇列名稱和佇列延遲時間Laravel事件佇列
- [Redis]延遲訊息佇列Redis佇列
- 我們一起來學RabbitMQ 三:RabbiMQ 死信佇列,延遲佇列,持久化等知識點MQ佇列持久化
- 實現延遲搜尋功能
- rabbitMQ 延遲佇列外掛強制呼叫ReturnCallback裡returnedMessage方法MQ佇列
- RabbitMQ釋出訂閱實戰-實現延時重試佇列MQ佇列