RabbitMQ Java客户端-如何明智地处理异常和关闭?

RabbitMQ Java客户端-如何明智地处理异常和关闭?,java,rabbitmq,amqp,Java,Rabbitmq,Amqp,以下是我目前所知道的(请纠正我): 在RabbitMQ Java客户机中,当出现一般网络故障(来自代理的数据格式错误、身份验证失败、丢失的心跳)时,通道上的操作会抛出IOException 通道上的操作还可能引发ShutdownSignalException未检查异常,通常是在通道/连接关闭后尝试对其执行操作时引发alreadcyclosedexception 关闭过程发生在以下情况下(例如,通过channel.close()或connection.close())。shutdown事件从Con

以下是我目前所知道的(请纠正我):

在RabbitMQ Java客户机中,当出现一般网络故障(来自代理的数据格式错误、身份验证失败、丢失的心跳)时,通道上的操作会抛出
IOException

通道上的操作还可能引发
ShutdownSignalException
未检查异常,通常是在通道/连接关闭后尝试对其执行操作时引发
alreadcyclosedexception

关闭过程发生在以下情况下(例如,通过channel.close()或connection.close())。shutdown事件从Connection->Channel->Consumer沿“拓扑”向下传播,当调用Consumer的
handleShutdown()方法的通道被调用时

用户还可以添加关机侦听器,该侦听器在关机过程完成后调用

我缺少的是:

  • 由于IOException表示网络故障,它是否也会启动关闭请求
  • 使用自动恢复模式如何影响关机请求?它是否会在尝试重新连接到通道时导致通道操作阻塞,或者仍然会引发ShutdowSignalException
  • 以下是我目前处理异常的方式,这是一种明智的方法吗?

    我的设置是轮询排队消费者并将任务分派到工作池。rabbitmq客户端封装在这里的
    MyRabbitMQWrapper
    中。当轮询队列时发生异常,我只是优雅地关闭所有东西并重新启动客户端。当worker中发生异常时,我也只是记录它并完成worker

    我最大的担忧(与问题1相关):假设工人中发生IOException,那么任务就不会得到确认。如果关闭没有发生,我现在有一个未确认的任务,它将永远处于不确定状态

    伪代码:

    class Main {
        public static void main(String[] args) {
            while(true) {
                run();
                //Easy way to restart the client, the connection has been
                //closed so RabbitMQ will re-queue any un-acked tasks.
                log.info("Shutdown occurred, restarting in 5 seconds");
                Thread.sleep(5000);
            }
        }
    
        public void run() {
          MyRabbitMQWrapper rw = new MyRabbitMQWrapper("localhost");
    
          try {
            rw.connect();
    
            while(!Thread.currentThread().isInterrupted()) {
               try {
                   //Wait for a message on the QueueingConsumer
                   MyMessage t = rw.getNextMessage();
                   workerPool.submit(new MyTaskRunnable(rw, t));
               } catch (InterruptedException | IOException | ShutdownSignalException e) {
                   //Handle all AMQP library exceptions by cleaning up and returning
                   log.warn("Shutting down", e);
                   workerPool.shutdown();
                   break;
               }
            }
          } catch (IOException e) {
            log.error("Could not connect to broker", e);
          } finally {
            try { 
                rw.close(); 
            } catch(IOException e) { 
                log.info("Could not close connection");
            }
          }
        }
    }
    
    class MyTaskRunnable implements Runnable {
        ....
    
        public void run() {
            doStuff();
            try {
                rw.ack(...);
            } catch (IOException | ShutdownSignalException e) {
                log.warn("Could not ack task");
            }
        }
    }
    

    您可以检查是否从意外的连接/通道/使用者关闭中自动恢复。

    我通过调用
    Channel.basicCancel(null)
    成功地引发了IOException。通道上的后续操作没有引发ShutdowsSignalException,因此答案是IOException不能保证关闭请求。因此IOException可能导致未确认的任务。。。我现在关闭了连接,并在发生IOException时重新启动。如果连接/通道关闭,未确认的消息将被推回到原始队列。Lyra不受欢迎。是否有其他选择?