指數退避
可以了解為每次重連失敗時,就把重連時間設定為之前的指數級别。例如 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() 實作定時任務邏輯。
參考
美團閃電俠用戶端啟動流程