【发布时间】:2016-10-09 23:50:42
【问题描述】:
我想获取几条消息,处理它们并在此之后将它们全部确认。所以基本上我收到一条消息,将其放入某个队列并继续接收来自兔子的消息。不同的线程将使用收到的消息监视此队列,并在数量足够时对其进行处理。我所能找到的关于 ack 的所有内容仅包含在同一线程上处理的一条消息的示例。像这样(来自官方文档):
channel.basicQos(1);
final Consumer consumer = new DefaultConsumer(channel) {
@Override
public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {
String message = new String(body, "UTF-8");
System.out.println(" [x] Received '" + message + "'");
try {
doWork(message);
} finally {
System.out.println(" [x] Done");
channel.basicAck(envelope.getDeliveryTag(), false);
}
}
};
文档也这样说:
通道实例不能在线程之间共享。应用 应该更喜欢每个线程使用一个 Channel 而不是共享同一个 跨多个线程的通道。虽然通道上的一些操作是 安全地同时调用,有些不是并且会导致不正确 帧在电线上交错。
所以我在这里很困惑。如果我正在确认一些消息,同时频道正在接收来自 rabbit 的另一条消息,那么它当时是否被认为是两个操作?在我看来是的。
我尝试从不同线程确认同一通道上的消息,它似乎有效,但文档说我不应该在线程之间共享通道。所以我尝试用不同的频道在不同的线程上做确认,但是失败了,因为这个频道的传递标签是未知的。
是否可以确认消息不在收到的同一线程上?
UPD 我想要的示例代码。它在 scala 中,但我认为它很简单。
case class AmqpMessage(envelope: Envelope, msgBody: String)
val queue = new ArrayBlockingQueue[AmqpMessage](100)
val consumeChannel = connection.createChannel()
consumeChannel.queueDeclare(queueName, true, false, true, null)
consumeChannel.basicConsume(queueName, false, new DefaultConsumer(consumeChannel) {
override def handleDelivery(consumerTag: String,
envelope: Envelope,
properties: BasicProperties,
body: Array[Byte]): Unit = {
queue.put(new AmqpMessage(envelope, new String(body)))
}
})
Future {
// this is different thread
val channel = connection.createChannel()
while (true) {
try {
val amqpMessage = queue.take()
channel.basicAck(amqpMessage.envelope.getDeliveryTag, false) // doesn't work
consumeChannel.basicAck(amqpMessage.envelope.getDeliveryTag, false) // works, but seems like not thread safe
} catch {
case e: Exception => e.printStackTrace()
}
}
}
【问题讨论】:
-
能否请您详细说明这部分
I want to fetch several messages, handle them and ack them all together after that. So basically I receive a message, put it in some **queue** and continue receiving messages from rabbit.**之间的队列是什么?另一个 RMQ 队列还是其他什么? -
@cantSleep现在只是简单的java内存阻塞队列。我已经发布了示例来澄清。抱歉误导。
-
"是否可以确认消息不在收到的同一线程上?"答案是“是”
标签: java multithreading rabbitmq