![](/img/trans.png)
[英]How do you handle recovering from a faulty connection using RabbitMQ java client library?
[英]RabbitMQ Java client - How to sensibly handle exceptions and shutdowns?
這是我目前所知的(請糾正我):
在RabbitMQ Java客戶端中,當存在一般網絡故障(來自代理的格式錯誤的數據,身份驗證失敗,錯過的心跳)時,通道上的操作會拋出IOException
。
通道上的操作也可以拋出ShutdownSignalException
未經檢查的異常,當我們在關閉后嘗試對通道/連接執行操作時,通常是AlreadyClosedException
。
關閉過程在“網絡故障,內部故障或顯式本地關閉” (例如通過channel.close()或connection.close())的情況下發生。 關閉事件沿着“拓撲”向下傳播,來自Connection - > Channel - > Consumer,當它調用的Channel調用Consumer的handleShutdown()
方法時。
用戶還可以添加在關閉過程完成后調用的關閉偵聽器。
這是我缺少的:
這是我現在處理異常的方式,這是一種明智的方法嗎?
我的設置是我正在輪詢QueueingConsumer並將任務分派給工作池。 rabbitmq客戶端封裝在MyRabbitMQWrapper
。 當輪詢隊列時發生異常時,我只是優雅地關閉所有內容並重新啟動客戶端。 當工作者發生異常時,我也只是記錄它並完成工作。
我最大的擔憂(與問題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");
}
}
}
您可以查看Lyra是否從意外的連接/通道/消費者關閉中自動恢復。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.