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