我们有一个独立的java应用程序在Debian机器上进行一些后台处理。它必须处理的作业是通过RabbitMQ消息发送的。
当需要升级java应用程序时,我们需要停止它(杀死它)。但我们必须确保没有消费者正在处理消息。根据您的经验,实现这一目标的最佳方法是什么?
我们尝试向消费者发送'SHUTDOWN'消息,但我们似乎无法关闭队列或频道?!它冻结了应用程序! 或者是否有另一种解决方案,我们可以自动关闭应用程序,而无需在linux中执行kill命令?
分享您的经验。
问候
答案 0 :(得分:3)
RabbitMQ Java库不提供(AFAIK)任何会在某些消息仍在处理时自动推迟关闭消费者进程的内容。因此,你必须自己做。
如果您的应用程序可以容忍它,请关闭。任何尚未在该点确认的消息将保留在代理内的队列中,并在消费者重新启动时重新发送。
如果您无法容忍,并且您必须确保所有正在进行的消息处理完成,那么您需要遵循与this answer中的内容类似的建议,并在关机处理程序中执行以下操作: / p>
这意味着您的每个消息处理线程(假设您有多个线程同时处理消息)需要遵循以下一般模式:
希望有所帮助。
答案 1 :(得分:0)
这是我的看法。
我创建了DefaultConsumer(BasicConsumer)的子类,它提供了isCancelled()并实现了handleCancelOk(),它将“cancelged flag”设置为true。
开始序列:
consumers = new ArrayList<BasicConsumer>();
consumers.add(...)
停止序列:
// Cancel all consumers
for (BasicConsumer consumer : consumers) {
try {
consumer.getChannel().basicCancel(consumer.getConsumerTag());
} catch (Exception e) {
// report
}
}
// Wait for all consumers to be cancelled
Timeout timeout = ...;
while (!consumers.isEmpty() && !timeout.isElapsed()) {
// Remove cancelled consumers
for (Iterator<BasicConsumer> iterator = consumers.iterator(); iterator.hasNext();) {
if (iterator.next().isCancelled())
iterator.remove();
}
}
// Here we could force-close the remaining timed-out consumers if we
// used our own ExecutorService by shutting down all of its threads.
connection.close();
相关的RabbitMQ ML线程:How to shutdown cleanly a Java application using Consumers?