【问题标题】:Using publisher confirms with RabbitMQ, in which cases publisher will be notified about success/failure?使用发布者与 RabbitMQ 确认,在哪些情况下会通知发布者成功/失败?
【发布时间】:2017-01-24 03:17:26
【问题描述】:

引用本书,RabbitMQ in Depth:

一个 Basic.Ack 请求被发送到一个发布者,当它有一个消息时 已发布已被所有消费者应用程序直接使用 它被路由到的队列或消息被排队和持久化 如有要求。

Has been directly consumed 混淆,是不是表示消费者发送ack 给代理发布者时会被告知消费者处理消息成功?或者这意味着当消费者刚刚从队列中收到消息时会通知发布者?

or that the message was enqueued and persisted if requested。当其中任何一种发生时,是否会通知发布者? (在这种情况下,发布者会收到两次通知)

使用node.jsamqplib 想检查实际发生了什么:

// consumer.js
amqp.connect(...)
.then(connection => connection.createChannel())
.then(() => { assert exchange here })
.then(() => { assert queue here })
.then(() => { bind queue and exchange here })
.then(() => {
  channel.consume(QUEUE, (message) => {
    console.log('Raw RabbitMQ message received', message)

    // Simulate some job to do
    setTimeout(() => {
      channel.ack(message, false)
    }, 5000})

  }, { noAck: false })
})

// publisher.js
amqp.connect(...)
.then(connection => connection.createConfirmChannel())
.then(() => { assert exchange here })
.then(() => {
  channel.publish(exchange, routingKey, new Buffer(...),{}, (err, ok) => {
    if (err) {
      console.log('Error from handling confirmation on publisher side', err)
    } else {
      console.log('From handling confirmation on publisher side', ok)
    }
  })
})

运行示例,我可以看到以下日志:

From handling confirmation on publisher side undefined
Raw RabbitMQ message received
Time to ack the message

据我所知,至少在这个日志中,只有在消息入队时才会通知发布者?(所以让消费者ack发送消息不会以任何方式影响发布者)

进一步引用:

如果无法路由消息,代理将发送 Basic.Nack RPC 指示失败的请求。然后由出版商决定 决定如何处理消息。

更改上面的示例,我只将消息的路由键更改为不应在任何地方路由的内容(没有与路由键匹配的绑定),从日志中我可以看到 only 关注。

From handling confirmation on publisher side undefined

现在我更困惑了,究竟是什么发布者在这里得到通知?我会理解它收到一个错误,例如Can't route anywhere,这将与上面的报价保持一致。但是正如您所看到的,err 没有定义,并且作为附带问题,即使他们的官方文档中的amqplib 使用的是(err, ok),在任何情况下我都没有看到这些定义。所以这里的输出和上面的例子一样,上面的例子和不可路由的消息有什么不同。

那么我在这里做什么,何时确切地通知发布者关于消息发生了什么?任何使用 PublisherConfirms 的具体示例?从上面的日志中,我得出的结论是,如果您希望 100% 确定该消息已入队,那么使用它是很好的。

【问题讨论】:

    标签: node.js rabbitmq amqp


    【解决方案1】:

    经过一次又一次的搜索,我找到了这个 http://www.rabbitmq.com/blog/2011/02/10/introducing-publisher-confirms/

    基本规则如下:

    1. 在 basic.return 之后立即确认不可路由的强制消息或即时消息
    2. 暂态消息在入队时得到确认
    3. 持久化消息在持久化到磁盘或在每个队列上被使用时得到确认。

    如果满足这些条件中的一个以上,则只有第一个会导致 确认发送。每一条发布的消息都会尽快得到确认 或更高版本,并且不会多次确认任何消息。

    【讨论】:

    • 我赞成这个答案,因为它是准确的,但我认为问题是问你如何在 javascript 中从那篇文章中获取这些事件。最流行的图书馆根本没有那么明显......
    【解决方案2】:

    默认情况下,发布者对消费者一无所知。

    PublisherConfirms 用于检查消息是否到达代理,但不检查消息是否已入队。

    您可以使用mandatory 标志来确保消息已被路由 看到这个https://www.rabbitmq.com/reliability.html

    为确保消息被路由到单个已知队列,生产者 可以只声明一个目标队列并直接发布到它。如果 消息可能会以更复杂的方式路由,但生产者仍然 需要知道他们是否到达了至少一个队列,它可以设置 basic.publish 上的强制标志,确保 basic.return (包含回复代码和一些文字说明)将被发送 如果没有适当绑定队列,则返回客户端。

    【讨论】:

    • 请检查我的答案,你的答案似乎不正确
    • 其实我的理解是发布者确认告诉你Rabbit有,不会丢的……上面接受的答案直接来自官博……
    【解决方案3】:

    我不完全确定关于 ack/nack 问题的通知,但请查看 BunnyBus 节点库以获得更简单的 api 和 RabbitMQ 管理:)

    https://github.com/xogroup/bunnybus

    const BunnyBus = require('bunnybus');
    const bunnyBus = new BunnyBus({
        user: 'your-user',
        vhost: 'your-vhost', // cloudamqp defaults vhost to the username
        password: 'your-password',
        server: 'your.server.com'
    });
    
    const handler = {
        'test.event': (message, ack) => {
    
            // Do your work here.
    
            // acknowledge the message off of the bus.
            return ack();
        }
    };
    
    // Create exchange and queue if they do not already exist and then auto connect.
    return bunnyBus.subscribe('test', handler)
        .then(() => {
    
            return bunnyBus.publish({event: 'test.event', body: 'here\'s the thing.'});
        })
        .catch(console.log);
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2020-02-01
      • 1970-01-01
      • 2022-08-24
      • 2020-03-13
      • 2020-06-23
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多