【问题标题】:Error when using Rebus with RabbitMQ exclusive queues将 Rebus 与 RabbitMQ 独占队列一起使用时出错
【发布时间】:2021-02-25 15:52:08
【问题描述】:

我在尝试使用 Rebus 响应 RabbitMQ 独占队列时遇到以下异常。

-       e   {"Queue 'xxxx-xxxx' does not exist"}    Rebus.Exceptions.RebusApplicationException

+       InnerException  {"The AMQP operation was interrupted: AMQP close-reason, initiated by Peer, code=405, text=\"RESOURCE_LOCKED - cannot obtain exclusive access to locked queue 'xxxx-xxxx' in vhost '/'. It could be originally declared on another connection or the exclusive property value does not match that of the original d...\", classId=50, methodId=10, cause="} System.Exception {RabbitMQ.Client.Exceptions.OperationInterruptedException}

客户端将队列声明为独占,并且能够成功地将消息发送到服务器。服务器处理消息,但在发送响应时抛出异常。

我可以在 Rebus 源代码 (Rebus.RabbitMq.RabbitMqTransport.cs) 中看到它尝试了 model.QueueDeclarePassive(queueName),它会引发上述异常。

我找到了以下语句Here

RabbitMQ 将排他性扩展到 queue.declare(包括被动声明)、queue.bind、queue.unbind、queue.purge、queue.delete、basic.consume 和 basic.get

修改 Rebus 源以简单地从 CheckQueueExistence 方法返回 true 允许发送响应消息。所以我的问题是,这是 Rebus 中在排他队列上使用被动声明的问题,是 RabbitMQ 阻塞了调用,还是我缺少一个基本概念?

【问题讨论】:

    标签: c# .net rabbitmq rebus


    【解决方案1】:

    Rebus 做model.QueueDeclarePassive(queueName) 的原因是因为它试图通过在发送到目标队列之前验证目标队列的存在来帮助您。

    这是为了避免发件人去的情况

    using var bus = Configure.With(...)
        .(...)
        .Routing(r => r.TypeBased().Map<string>("does-not-exist"))
        .Start();
    
    await bus.Send("I'M LOST ?");
    

    消息丢失了。

    这里的问题是,RabbitMQ 仍然使用路由键将发送的消息与指向队列的绑定匹配,如果不存在匹配的绑定(即使使用 DIRECT 交换类型),消息只是路由到 0 个队列,因此它丢失了。

    如果您提交的 PR 可以配置是否检查目标队列是否存在,那么我很乐意(帮助您正确处理并)接受它。

    【讨论】:

    • 感谢您的回复。我遇到了为我们正在考虑实施的更改做一个小的 POC 的问题,我们现在使用的是旧版本的 Rebus,如果我们决定更多地查看独占队列和 Rebus 升级,我会建议团队再看看这个,看看是否需要 PR。干杯。