我正在遵循以下教程: 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 &
答案 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)
})