带有 AMQP 和 RabbitMQ 的 Spring,带有可选 x-dead-letter-exchange 的队列

Posted

技术标签:

【中文标题】带有 AMQP 和 RabbitMQ 的 Spring,带有可选 x-dead-letter-exchange 的队列【英文标题】:Spring with AMQP and RabbitMQ, queue with optional x-dead-letter-exchange 【发布时间】:2015-11-03 11:51:02 【问题描述】:

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

这是我在 Spring 中声明队列的 ​​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 中指定它),只是看到此消息的不同变体。

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

【问题讨论】:

在声明 RabbitMQ 对象时,例如队列和交换,您必须指定完全相同的参数,RabbitMQ 不会为您执行任何类型的参数合并。我不知道你是怎么用 spring 做到这一点的。 【参考方案1】:

正如您在spring docs 中看到的:The RabbitMQ broker will not allow declaration of a queue with mismatched arguments.,所以您不能这样做。 在 RabbitMQ Java API 中有一个方法可以检查队列是否已经存在:queueDeclarePassive

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

【讨论】:

【参考方案2】:

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

解决这个问题

删除您手动创建的所有队列,让客户端程序自行创建。 如果你在删除队列时遇到问题,因为里面有一些数据,或者出于某种原因,你想维护它,手动创建一个队列,然后将所有要删除的队列数据通过“队列的“移动”选项卡。

【讨论】:

删除队列并让它们在应用程序启动时创建为我解决了【参考方案3】:

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

解决办法:

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

希望这会有所帮助。

【讨论】:

【参考方案4】:

发件人:https://github.com/jondot/sneakers/issues/121

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

【讨论】:

以上是关于带有 AMQP 和 RabbitMQ 的 Spring,带有可选 x-dead-letter-exchange 的队列的主要内容,如果未能解决你的问题,请参考以下文章

面临通过rabbitmq(amqp协议)从云向设备iot hub发送消息的问题

spring 集成是不是支持带有 ActiveMq 的 AMQP

带有 AMQP 的 Golang 中的 JSON RPC

如何使用 JMS 和 AMQP 1.0 设置 RabbitMQ?

理解RabbitMQ中的AMQP-0-9-1模型

理解RabbitMQ中的AMQP-0-9-1模型