天天看點

Netty 用戶端使用指數退避機制實作重連

指數退避

可以了解為每次重連失敗時,就把重連時間設定為之前的指數級别。例如 2 秒,4 秒,8 秒......

亞馬遜AWS關于指數退避的兩篇文章介紹

  • AWS 中的錯誤重試和指數退避
  • Exponential Backoff And Jitter

Netty用戶端中使用指數退避方式重連

用戶端連接配接伺服器時,調用 Bootstrap 的 connect 方法:

bootstrap.connect(host, port)           

這個方法會傳回 ChannelFuture ,ChannelFuture 實作了 netty 的 Future , 而Future 繼承自 java.util.concurrent.Future ,這是異步操作的結果,是以 connect 方法是一個異步方法。我們可以通過調用addListener 添加監聽器,監聽是否連接配接成功。

  • 這裡使用 GenericFutureListener ,也可以使用 ChannelFutureListener 這個接口。
/**
     * 連接配接和重連機制,實作了指數退避重連
     * @param bootstrap
     * @param host
     * @param port
     * @param retry
     */
    private static void connect(Bootstrap bootstrap, String host, int port, int retry) {

        bootstrap.connect(host, port).addListener(new GenericFutureListener<Future<? super Void>>() {
            @Override
            public void operationComplete(Future<? super Void> future) throws Exception {
                if (future.isSuccess()) {
                    LOGGER.info("連接配接伺服器成功!");
                } else if (retry == 0) {
                    LOGGER.error("重連次數已用完,放棄連接配接!");
                } else {
                    // 第幾次重連
                    int order = (MAX_RETRY - retry) + 1;
                    // 本次重連的間隔
                    int delay = 1 << order;
                    LOGGER.error(new Date() + ": 連接配接失敗,第" + order + "次重連……");

                    bootstrap.config().group().schedule(() -> connect(bootstrap, host, port, retry - 1), delay, TimeUnit.SECONDS);
                }
            }
        });
    }           
  • 通過future.isSuccess() 判斷是否連接配接成功。
  • int delay = 1 << order; 通過左移操作快速計算出重連時間間隔。
  • bootstrap.config().group().schedule() 實作定時任務邏輯。

參考

美團閃電俠用戶端啟動流程