通过运行RabbitMQ使用者安全地结束Java应用程序的最佳方法是什么?

我们有一个独立的java应用程序在Debian机器上进行一些后台处理。 它必须处理的作业是通过RabbitMQ消息发送的。

当需要升级java应用程序时,我们需要停止它(杀死它)。 但我们必须确保没有消费者正在处理消息。 根据您的经验,实现这一目标的最佳方法是什么?

我们尝试向消费者发送“SHUTDOWN”消息,但我们似乎无法关闭队列或频道?! 它冻结了应用程序! 或者是否有另一种解决方案,我们可以自动关闭应用程序,而无需在linux中执行kill命令?

谢谢分享你的经验。

问候

RabbitMQ Java库不提供(AFAIK)任何会在某些消息仍在处理时自动推迟关闭消费者进程的内容。 因此,你必须自己做。

如果您的应用程序可以容忍它,请关闭。 任何尚未在此时确认的消息将保留在代理内的队列中,并在消费者重新启动时重新发送。

如果您无法容忍,并且您必须确保所有正在进行的消息处理完成,那么您需要遵循与此答案中的内容类似的建议,并在关机处理程序中执行以下操作:

  1. 将“所有线程应退出”标志设置为true
  2. 加入线程池中的每个线程
  3. 优雅地退出

这意味着您的每个消息处理线程(假设您有多个线程同时处理消息)需要遵循以下一般模式:

  1. 从队列中提取消息并进行处理
  2. 确认刚处理过的消息
  3. 如果“所有线程应退出”标志为true,则退出线程函数
  4. 冲洗,重复

希望有所帮助。

这是我的看法。

我创建了DefaultConsumer(BasicConsumer)的子类,它提供了isCancelled()并实现了handleCancelOk(),它将“已取消的标志”设置为true。

开始顺序:

consumers = new ArrayList(); 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 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线程: 如何使用消费者干净地关闭Java应用程序?