一、微信掃碼支付流程
超過限定時間(30分鐘)並未支付的訂單,我們需要進行超時訂單的處理:先調用微信支付api,查詢該訂單的支付狀態。如果未支付調用關閉訂單的api,並修改訂單狀態爲已關閉,並回滾庫存數。如果該訂單已經支付,則做補償操作(修改訂單狀態和記錄)。
使用延遲消息隊列(死信隊列)來實現。就是消息的生產者發送的消息並不會立刻被消費,而是在設定的時間之後纔可以消費。
我們可以在訂單創建時發送一個延遲消息,消息爲訂單號,系統會在限定時間之後取出這個消息,然後
查詢訂單的支付狀態,根據結果做出相應的處理
超時訂單處理
死信交換機
一個消息在滿足如下條件下,會進死信交換機,記住這裏是交換機而不是隊列,一個交換機可以對應很
多隊列。
(1) 一個消息被Consumer拒收了,並且reject方法的參數裏requeue是false。也就是說不會被再次
放在隊列裏,被其他消費者使用。
(2)上面的消息的TTL到了,消息過期了。
(3)隊列的長度限制滿了。排在前面的消息會被丟棄或者扔到死信交換機上。
Dead Letter Exchange 其實就是一種普通的exchange,和創建其他exchange沒有兩樣。只是在某一個
設置Dead Letter Exchange的隊列中有消息過期了,會自動觸發消息的轉發,發送到Dead Letter
Exchange中去。
(1)創建死信交換器機
// 定義死信交換機
@Bean(ORDER_EXCHANGE_DLX)
public Exchange orderExchangeDLX() {
return ExchangeBuilder.topicExchange(ORDER_EXCHANGE_DLX).durable(true).build();
}
(2)創建超時隊列
// 聲明正常超時隊列
@Bean(ORDER_QUEUE)
public Queue order1() {
return QueueBuilder.durable(ORDER_QUEUE)
.withArgument("x-dead-letter-exchange", ORDER_EXCHANGE_DLX) //死信交換機名稱
.withArgument("x-dead-letter-routing-key", "dlx.order.cancel") //死信隊列的路由key
.withArgument("x-message-ttl", 60000*10) // 設置隊列的過期時間10分鐘
.build();
}
(3)創建死信隊列
// 聲明死信隊列
@Bean(ORDER_QUEUE_DLX)
public Queue order2() {
return QueueBuilder.durable(ORDER_QUEUE_DLX).build();
}
(4)建立死信交換機與延時隊列之間的綁定
// 綁定死信交換機和死信隊列
@Bean
public Binding bindingExchange2(@Qualifier(ORDER_QUEUE_DLX) Queue queue,
@Qualifier(ORDER_EXCHANGE_DLX) Exchange exchange) {
return BindingBuilder.bind(queue).to(exchange).with("dlx.order.#").noargs();
}
(5)測試:向超時隊列添加消息,等待10秒後消息從隊列消失