使用AMQP和RabbitMQ的Spring,使用可选的x-dead-letter-exchange排队

时间:2015-08-11 09:54:49

标签: java spring rabbitmq amqp spring-amqp

我在RabbitMQ中创建了一个现有队列。可以使用或不使用x-dead-letter-exchange参数创建它。我正在使用RabbitTemplate在Spring中创建此队列的使用者。当我声明队列时,我不想指定x-dead-letter-exchange参数。我希望模板以某种方式表现出来或不关心。我从我的消费者那里抛出AmqpRejectAndDontRequeueException来表示不良消息,但我希望队列的创建者负责决定是否为被拒绝的消息创建交换和队列。

这是我在bean中声明队列的bean:

@Bean
Queue queue() {
    Map<String, Object> args = new HashMap<>();
    // set the queue with a dead letter feature
    args.put("x-dead-letter-exchange", REJECTED_EXCHANGE);
    args.put("x-dead-letter-routing-key", REJECTED_ROUTING_KEY);
    Queue queue = new Queue(Constants.QUEUE_NAME, false, false, false, args);
    return queue;
}

这很好用,但是当队列的创建者决定不使用死信功能时,我看到以下错误:

Channel shutdown: channel error; protocol method: #method<channel.close>
(reply-code=406, reply-text=PRECONDITION_FAILED - 
inequivalent arg 'x-dead-letter-exchange' for queue 'queueName'

消息有点长,它继续告诉我哪一方有x-dead-letter-exchange(没有或交换名称)。我尝试了不同的组合(例如,在Spring中创建队列,而不是在Spring中指定它,或者在没有交换的情况下创建队列并在Spring中指定它),只是为了看到此消息的不同变体。

如何声明队列,以便它只接受队列中已设置的任何参数?

4 个答案:

答案 0 :(得分:3)

正如您在endiannessThe RabbitMQ broker will not allow declaration of a queue with mismatched arguments.中看到的那样,所以你无法做到。
在RabbitMQ Java API中,有一种方法可以检查队列是否已存在:queueDeclarePassive

如果Spring AMQP API提供了类似的功能,您可以在尝试声明队列之前使用它。

答案 1 :(得分:0)

是,可能的原因是-如果手动声明一些队列,然后程序(代码中的客户端)尝试创建一个队列(基于代码中的设置),则会出现此错误。其背后的原因是您的代码(客户端应用程序)尝试访问一个队列时。从服务器收到一个信号,表明该连接不可用。

要解决此问题

  • 删除所有手动创建的队列,然后让客户端程序自行创建它们。
  • 如果由于存在队列中的某些数据或出于某种原因而要删除队列时遇到问题,则您要对其进行维护,手动创建一个队列,然后将所有要删除的队列数据通过“队列中的“移动”标签。

答案 2 :(得分:0)

是的,当您在RabbitMQ中手动创建交换或队列然后您的应用程序尝试创建另一个队列时,会发生这种问题,并且它会找到具有不同属性/配置的相同队列或交换,从而显示配置不匹配。

解决方案:

允许您的应用程序仅创建交换和队列。

希望这会有所帮助。

答案 3 :(得分:0)

来自:https://github.com/jondot/sneakers/issues/121

尝试完成队列中的所有消息,删除队列,然后 请尝试使用上面失败的代码重新声明它。我想你会 发现此特定错误消失了