簡體   English   中英

RabbitMQ Java客戶端 - 如何合理地處理異常和關閉?

[英]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()方法時。

用戶還可以添加在關閉過程完成后調用的關閉偵聽器。

這是我缺少的:

  1. 由於IOException指示網絡故障,它是否也會啟動關閉請求?
  2. 使用自動恢復模式如何影響關閉請求? 是否會導致通道操作在嘗試重新連接到通道時阻塞,或者是否仍會拋出ShutdownSignalException?

這是我現在處理異常的方式,這是一種明智的方法嗎?

我的設置是我正在輪詢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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM