我如何让RabbitMQ重新发送未确认的消息?

时间:2017-10-09 20:33:27

标签: rabbitmq

我正在遵循以下教程: https://www.rabbitmq.com/tutorials/tutorial-two-java.html

我这样启动RabbitMQ服务器:

docker pull rabbitmq
docker run -d --hostname my-rabbit-host --name my-rabbit -p 5672:5672 rabbitmq:3

从教程:

  

使用此代码我们可以确定即使你使用了杀死一个工人   在处理消息时CTRL + C,什么都不会丢失。不久   在工人死亡之后,所有未经确认的消息将被重新传递。

我产生了两个消费者,当我在其中一个CTRL + C时,另一个正在运行的消费者接收最初发往前消费者的消息。如何在CTRL + C中消除其中一个消费者后重新传递消息?

编辑:我现在正在通过'brew'安装RabbitMQ,但我仍然看到同样的问题。

brew update
brew install rabbitmq
/usr/local/sbin/rabbitmq-server &

2 个答案:

答案 0 :(得分:0)

没有必要在消费者代码中放置睡眠或类似内容。在您提供的链接上,搜索以手动消息确认开头的段落,并查看其中的代码。关键是不要承认这个消息。如果你将autoACK标志设置为true,那么你可以调用你想要的任何东西,一旦收到消息就会被确认。因此,只需不设置该标志,并且为了测试,您可以注释掉行channel.basicAck(envelope.getDeliveryTag(), false);,以便不进行手动ACK。因此,当消费者退出时,消息仍将在队列中。

答案 1 :(得分:0)

奇怪,RabbitMQ开箱即用。

步骤1 ,我启动了RabbitMQ:

$ docker run -d --hostname my-rabbit-host --name my-rabbit -p 5672:5672 rabbitmq:3
$ docker ps
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS                                                   NAMES
e0c3257b8b49        rabbitmq:3          "docker-entrypoint.s…"   18 minutes ago      Up 14 minutes       4369/tcp, 5671/tcp, 25672/tcp, 0.0.0.0:5672->5672/tcp   my-rabbit

第2步,我发布了一条消息(顺便说一下,我尝试使用Node.js。有关源代码,请参见下面的附录):

$ node src/producer.js
Publisher:  TODO 1st

第3步,我一个接一个地启动了两个使用者(出于测试目的,我的使用者被设计为不承认,因此RabbitMQ永远不会使消息出队)。

消费者1将收到该消息,而消费者2将不会。

消费者1:

$ node src/consumer.js 
Consumer:  TODO 1st

消费者2:

$ node src/consumer.js 

步骤4 ,当我通过“ Ctrl + c”停止使用方1时,使用方2将立即收到RabbitMQ的消息:

消费者2:

$ node src/consumer.js 
Consumer:  TODO 1st

结论:基本上,在设置使用者时,我们需要告诉RabbitMQ在收到使用者的确认之前不要使消息出队。结果,如果使用者1在有机会确认消息之前由于某种原因而停止,RabbitMQ会将消息重新传递给使用者2。

附录

src / producer.js

var q = 'tasks'

function bail (err) {
  console.error(err)
  process.exit(1)
}

// Publisher
function publisher (conn) {
  conn.createChannel(onOpen)
  function onOpen (err, ch) {
    if (err != null) bail(err)
    ch.assertQueue(q)
    const msg = 'TODO 1st'
    ch.sendToQueue(q, Buffer.from(msg), { persistent: true })
    console.log('Publisher: ', msg)
  }
}

require('amqplib/callback_api')
  .connect('amqp://guest:guest@localhost', function (err, conn) {
    if (err != null) bail(err)
    publisher(conn)
  })

src / consumer.js

var q = 'tasks'

function bail (err) {
  console.error(err)
  process.exit(1)
}

// Consumer
function consumer (conn) {
  conn.createChannel(onOpen)
  function onOpen (err, ch) {
    if (err != null) bail(err)
    ch.assertQueue(q)
    ch.consume(q, function (msg) {
      if (msg !== null) {
        console.log('Consumer: ', msg.content.toString())
        // Commented out the line below, so RabbitMQ never dequeues a message
        // ch.ack(msg)
      }
    }, { noAck: false })
  }
}

require('amqplib/callback_api')
  .connect('amqp://guest:guest@localhost', function (err, conn) {
    if (err != null) bail(err)
    consumer(conn)
  })
相关问题