2015-11-22 61 views
0

我已經閱讀了有關該主題的多個答案,看起來我的配置應該正常工作,但由於某種原因它沒有。基於Spring Boot的應用程序中的死信路由

這裏是配置:

@Bean Queue intakeQueue(String name) { return new Queue(name, true); } 

@Bean Exchange dlx(String name) { return new DirectExchange(name); } 

@Bean Queue dlq(String name) { return new Queue(name, false, false, true); } 

@Bean 
Binding dlb(Exchange dlx, Queue dlq, Queue reply) { 
    return BindingBuilder.bind(dlq).to(dlx).with(reply.getName()).noargs(); 
} 

@Bean 
Queue replyQueue(String name, Exchange dlx) { 
    Map<String, Object> args = new HashMap<>(); 
    args.put("x-dead-letter-exchange", dlx.getName()); 
    args.put("x-dead-letter-routing-key", name); 
    return new Queue(name, true, false, false, args); 
} 

RabbitMQ的UI顯示,應答隊列具有DLXDLK和屬性。

我發送消息等

this.rabbit.convertSendAndReceive(intakeQueue, obj, message -> { 
    message.getMessageProperties().setPriority(10); 
    return message; 
}); 

消息處理程序拋出AmqpRejectAndDontRequeueException它接收到消息之後立即。這僅僅是爲了測試而完成的。我已經開始使用重試建議,但由於它沒有產生任何結果,我簡化了測試用例。

public Object handleMessage(Object obj) throws IOException { 
    throw new AmqpRejectAndDontRequeueException("Testing retries!"); 
} 

有兩個問題我現在看到的:ARADRE已經拋出後DLQ

  1. 消息一直沒有出現。如果我直接從handleMessage發佈到DLQ,它的確如此。
  2. convertSendAndReceive不收回任何東西(例外也許?),並等待,直到超時發生,這是5分鐘在我的情況。它可能是有意的,但對於RPC風格的調用來說,這很奇怪。

我是否錯過或錯誤配置了某些東西?

回答

1

在這個意義上,它不是RPC;在偵聽器中拋出異常將不會傳播回發件人。

您正在拒絕在intakeQueue上的交付,並且該消息將被路由到 DLX/DLQ(如果已配置)。

對於您的測試案例,您應該查看,即 DLQ(如果有的話),而不是回覆隊列的DLQ。

RabbitMQ不知道隊列關係。您不顯示容器或RabbitTemplate配置,但默認情況下使用直接replyTo路由(使用「特殊」內部隊列)。

您可以配置兔子模板以使用固定的回覆隊列,但您必須提供回覆監聽器容器as described in the documentation

如果收到回覆時發件人已超時,則模板將引發ARADRE,以便在該情況下回復將被刪除。

爲了測試,睡在你的監聽器中超過超時時間,然後回覆;您應該看到答覆轉到答覆隊列的DLQ。

如果你想傳播一個例外給調用者,你需要返回它作爲handleMessage返回值。

現在沒有重新拋出這種異常的邏輯,但是,您必須在您的代碼中執行此操作(檢測到回覆是異常並重新拋出異常)。

當然,例外類型必須是Serializable

您也可以使用Spring Remoting over AMQP其中負責傳播異常。

+0

好的,所以這是DLQ的攝入量而不是回覆。我想我被DLQ配置爲回覆的'FixedReplyQueueDeadLetterTests.java'這樣的例子搞糊塗了。我想我會在所有回覆嘗試都用盡時從消息恢復器中發回部分序列化的異常。從處理程序返回對象而不是異常將不會觸發所需的重試。謝謝,這有很多幫助,現在可以使用! –

相關問題