这或许是实现重试最优雅的姿势了!
使用場景
在日常開發(fā)中,我們經(jīng)常會遇到需要調用外部服務和接口的場景。外部服務對于調用者來說一般都是不可靠的,尤其是在網(wǎng)絡環(huán)境比較差的情況下,網(wǎng)絡抖動很容易導致請求超時等異常情況,這時候就需要使用失敗重試策略重新調用 API 接口來獲取。重試策略在服務治理方面也有很廣泛的使用,通過定時檢測,來查看服務是否存活(Active)。
Guava Retrying 是一個靈活方便的重試組件,包含了多種的重試策略,而且擴展起來非常容易。
用作者的話來說:
This is a small extension to Google’s Guava library to allow for the creation of configurable retrying strategies for an arbitrary function call, such as something that talks to a remote service with flaky uptime.
使用 Guava-retrying 你可以自定義來執(zhí)行重試,同時也可以監(jiān)控每次重試的結果和行為,最重要的基于 Guava 風格的重試方式真的很方便。
代碼示例
以下會簡單列出 guava-retrying 的使用方式:
-
如果拋出 IOException 則重試,如果返回結果為 null 或者等于 2 則重試,固定等待時長為 300 ms,最多嘗試 3 次;
-
出現(xiàn)異常則執(zhí)行重試,每次任務執(zhí)行最長執(zhí)行時間限定為 3 s,重試間隔時間初始為 3 s,最多重試 1 分鐘,隨著重試次數(shù)的增加每次遞增 1 s,每次重試失敗,打印日志;
核心執(zhí)行邏輯
long startTime = System.nanoTime(); for (int attemptNumber = 1; ; attemptNumber++) {Attempt<V> attempt;try {// 執(zhí)行成功V result = attemptTimeLimiter.call(callable);attempt = new ResultAttempt<V>(result, attemptNumber, TimeUnit.NANOSECONDS.toMillis(System.nanoTime() - startTime));} catch (Throwable t) {// 執(zhí)行失敗attempt = new ExceptionAttempt<V>(t, attemptNumber, TimeUnit.NANOSECONDS.toMillis(System.nanoTime() - startTime));}// 監(jiān)聽器處理for (RetryListener listener : listeners) {listener.onRetry(attempt);}// 是否符合終止策略if (!rejectionPredicate.apply(attempt)) {return attempt.get();}// 是否符合停止策略if (stopStrategy.shouldStop(attempt)) {thrownew RetryException(attemptNumber, attempt);} else {// 計算下次重試間隔時間long sleepTime = waitStrategy.computeSleepTime(attempt);try {blockStrategy.block(sleepTime);} catch (InterruptedException e) {Thread.currentThread().interrupt();thrownew RetryException(attemptNumber, attempt);}} }依賴引入
<dependency><groupId>com.github.rholder</groupId><artifactId>guava-retrying</artifactId><version>2.0.0</version> </dependency>默認的guava中也有包含。
主要接口介紹
-
Attempt:一次執(zhí)行任務;
-
AttemptTimeLimiter:單次任務執(zhí)行時間限制(如果單次任務執(zhí)行超時,則終止執(zhí)行當前任務);
-
BlockStrategies:任務阻塞策略(通俗的講就是當前任務執(zhí)行完,下次任務還沒開始這段時間做什么……),默認策略為:BlockStrategies.THREAD_SLEEP_STRATEGY 也就是調用 Thread.sleep(sleepTime);
-
RetryException:重試異常;
-
RetryListener:自定義重試監(jiān)聽器,可以用于異步記錄錯誤日志;
-
StopStrategy:停止重試策略,提供三種:
-
StopAfterDelayStrategy :設定一個最長允許的執(zhí)行時間;比如設定最長執(zhí)行10s,無論任務執(zhí)行次數(shù),只要重試的時候超出了最長時間,則任務終止,并返回重試異常RetryException;
-
NeverStopStrategy :不停止,用于需要一直輪訓知道返回期望結果的情況;
-
StopAfterAttemptStrategy :設定最大重試次數(shù),如果超出最大重試次數(shù)則停止重試,并返回重試異常;
-
-
WaitStrategy:等待時長策略(控制時間間隔),返回結果為下次執(zhí)行時長:
-
FixedWaitStrategy:固定等待時長策略;
-
RandomWaitStrategy:隨機等待時長策略(可以提供一個最小和最大時長,等待時長為其區(qū)間隨機值)
-
IncrementingWaitStrategy:遞增等待時長策略(提供一個初始值和步長,等待時間隨重試次數(shù)增加而增加)
-
ExponentialWaitStrategy:指數(shù)等待時長策略;
-
FibonacciWaitStrategy :Fibonacci 等待時長策略;
-
ExceptionWaitStrategy :異常時長等待策略;
-
CompositeWaitStrategy :復合時長等待策略;
-
總結
以上是生活随笔為你收集整理的这或许是实现重试最优雅的姿势了!的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 创业互联网公司如何搭建自己的技术架构
- 下一篇: 京东把 Elasticsearch 用的