2015-11-22 46 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'这样的例子搞糊涂了。我想我会在所有回复尝试都用尽时从消息恢复器中发回部分序列化的异常。从处理程序返回对象而不是异常将不会触发所需的重试。谢谢,这有很多帮助,现在可以使用! –

相关问题