guava-retrying 重試組件

一猪半、定義

重試機(jī)制可以保護(hù)系統(tǒng)減少因網(wǎng)絡(luò)波動(dòng)兔朦、依賴服務(wù)短暫性不可用帶來的影響,讓系統(tǒng)能更穩(wěn)定的運(yùn)行的一種保護(hù)機(jī)制磨确。

二沽甥、實(shí)現(xiàn)

因?yàn)間uava-retrying是基于Google的核心類庫guava的重試機(jī)制實(shí)現(xiàn),所以需要依賴guava的包乏奥,這里記得引入下摆舟。例子如下:

Retryer<Boolean> retryer = RetryerBuilder.<Boolean>newBuilder()
        .retryIfException()
        .retryIfResult(aBoolean -> Objects.equals(aBoolean, false))
        .withAttemptTimeLimiter(AttemptTimeLimiters.fixedTimeLimit(10, TimeUnit.SECONDS, Executors.newCachedThreadPool()))
        .withWaitStrategy(WaitStrategies.fixedWait(5, TimeUnit.SECONDS))
        .withStopStrategy(StopStrategies.stopAfterAttempt(5))
        .withRetryListener(new RetryListener() {
            @Override
            public <V> void onRetry(Attempt<V> attempt) {
                System.out.print("retry time=" + attempt.getAttemptNumber());
            }
        }).build();
try {
    retryer.call(() -> {
        // 邏輯處理
        return null;
    });
} catch (Exception e) {
    System.out.println("exception:" + e);
}

這就是一個(gè)重試機(jī)制的實(shí)現(xiàn)了,比較簡(jiǎn)單邓了,我們來看下具體接口及相應(yīng)的策咯恨诱。

  • newBuilder:創(chuàng)建RetryerBuilder對(duì)象,通過該類進(jìn)行構(gòu)建各種重試策咯骗炉;
  • retryIfException:拋出異常時(shí)重試照宝,但拋出error不會(huì)重試;另外該方法還包含一個(gè)重載的方法句葵,可以自定義針對(duì)異常的實(shí)現(xiàn)厕鹃;
  • retryIfRuntimeException:見名知義,拋出RuntimeException時(shí)重試笼呆;
  • retryIfExceptionOfType:拋出指定異常類型時(shí)重試熊响;
  • retryIfResult:根據(jù)具體的返回值選擇重試;
  • withRetryListener:在重試的時(shí)候進(jìn)行事件監(jiān)聽诗赌,這中間我們可以記錄下錯(cuò)誤日志什么的汗茄;可以注冊(cè)多個(gè)事件監(jiān)聽器,會(huì)按照注冊(cè)順序依次調(diào)用铭若;
  • withWaitStrategy:重試等待策略洪碳,核心策咯之一;
  • withStopStrategy:重試停止策略叼屠,核心策咯之一瞳腌;
  • withBlockStrategy:重試阻塞策略,也就是兩次重試的時(shí)間間隔的實(shí)現(xiàn)方式镜雨;
  • withAttemptTimeLimiter:?jiǎn)未稳蝿?wù)執(zhí)行時(shí)長(zhǎng)限制(如果單次任務(wù)執(zhí)行超時(shí)嫂侍,則終止執(zhí)行當(dāng)前任務(wù));
  • build:通過newBuilder構(gòu)建了各種重試策咯荚坞,構(gòu)建完成挑宠,還需要通過build方法借助Retryer來執(zhí)行;

接下來颓影,我們來看一下主要的幾個(gè)策咯及核心類各淀。

1. WaitStrategies 重試等待策略
1.1 ExponentialWaitStrategy 指數(shù)等待策略

指數(shù)補(bǔ)償 算法 Exponential Backoff

.withWaitStrategy(WaitStrategies.exponentialWait(100, 5, TimeUnit.MINUTES))

創(chuàng)建一個(gè)永久重試的重試器,每次重試失敗時(shí)以遞增的指數(shù)時(shí)間等待诡挂,直到最多5分鐘碎浇。 5分鐘后临谱,每隔5分鐘重試一次。對(duì)該例而言:

第一次失敗后奴璃,依次等待時(shí)長(zhǎng):2^1 * 100;2^2 * 100悉默;2^3 * 100;...

在ExponentialWaitStrategy中,根據(jù)重試次數(shù)計(jì)算等待時(shí)長(zhǎng)的源碼我們可以關(guān)注下:

@Override
public long computeSleepTime(Attempt failedAttempt) {
    double exp = Math.pow(2, failedAttempt.getAttemptNumber());
    long result = Math.round(multiplier * exp);
    if (result > maximumWait) {
        result = maximumWait;
    }
    return result >= 0L ? result : 0L;
}

如果以后有類似的需求溺健,我們可以自己寫下這些算法麦牺,而有關(guān)更多指數(shù)補(bǔ)償 算法 Exponential Backoff,可以參考:http://en.wikipedia.org/wiki/Exponential_backoff


1.2 FibonacciWaitStrategy 斐波那契等待策略

Fibonacci Backoff 斐波那契補(bǔ)償算法

.withWaitStrategy(WaitStrategies.fibonacciWait(100, 2, TimeUnit.MINUTES))

創(chuàng)建一個(gè)永久重試的重試器鞭缭,每次重試失敗時(shí)以斐波那契數(shù)列來計(jì)算等待時(shí)間剖膳,直到最多2分鐘;2分鐘后岭辣,每隔2分鐘重試一次吱晒;對(duì)該例而言:

第一次失敗后,依次等待時(shí)長(zhǎng):1*100;1*100沦童;2*100仑濒;3*100;5*100偷遗;...


1.3 FixedWaitStrategy 固定時(shí)長(zhǎng)等待策略
withWaitStrategy(WaitStrategies.fixedWait(10,  TimeUnit.SECONDS))

固定時(shí)長(zhǎng)等待策略墩瞳,失敗后,將等待固定的時(shí)長(zhǎng)進(jìn)行重試氏豌;


1.4 RandomWaitStrategy 隨機(jī)時(shí)長(zhǎng)等待策略
withWaitStrategy(WaitStrategies.randomWait(10,  TimeUnit.SECONDS));
withWaitStrategy(WaitStrategies.randomWait(1,  TimeUnit.SECONDS, 10, TimeUnit.SECONDS));

隨機(jī)時(shí)長(zhǎng)等待策略喉酌,可以設(shè)置一個(gè)隨機(jī)等待的最大時(shí)長(zhǎng),也可以設(shè)置一個(gè)隨機(jī)等待的時(shí)長(zhǎng)區(qū)間泵喘。


1.5 IncrementingWaitStrategy 遞增等待策略
withWaitStrategy(WaitStrategies.incrementingWait(1,  TimeUnit.SECONDS, 5, TimeUnit.SECONDS))

遞增等待策略泪电,根據(jù)初始值和遞增值,等待時(shí)長(zhǎng)依次遞增纪铺。就本例而言:

第一次失敗后相速,將依次等待1s;6s(1+5)鲜锚;11(1+5+5)s突诬;16(1+5+5+5)s;...


1.6 ExceptionWaitStrategy 異常等待策略
withWaitStrategy(WaitStrategies.exceptionWait(ArithmeticException.class, e -> 1000L))

根據(jù)所發(fā)生的異常指定重試的等待時(shí)長(zhǎng)芜繁;如果異常不匹配攒霹,則等待時(shí)長(zhǎng)為0;


1.7 CompositeWaitStrategy 復(fù)合等待策略
.withWaitStrategy(WaitStrategies.join(WaitStrategies.exceptionWait(ArithmeticException.class, e -> 1000L),WaitStrategies.fixedWait(5, TimeUnit.SECONDS)))

復(fù)合等待策略;如果所執(zhí)行的程序滿足一個(gè)或多個(gè)等待策略吼野,那么等待時(shí)間為所有等待策略時(shí)間的總和跨嘉。

2. StopStrategies 重試停止策略
2.1 NeverStopStrategy
withStopStrategy(StopStrategies.neverStop())

一直不停止,一直需要重試短条。


2.2 StopAfterAttemptStrategy
withStopStrategy(StopStrategies.stopAfterAttempt(3))

在重試次數(shù)達(dá)到最大次數(shù)之后剑辫,終止任務(wù)阱飘。


2.3 StopAfterDelayStrategy
withStopStrategy(StopStrategies.stopAfterDelay(3, TimeUnit.MINUTES))

在重試任務(wù)達(dá)到設(shè)置的最長(zhǎng)時(shí)長(zhǎng)之后摘昌,無論任務(wù)執(zhí)行次數(shù)速妖,都終止任務(wù)。

3. BlockStrategies 阻塞策略

阻塞策略默認(rèn)提供的只有一種:ThreadSleepStrategy聪黎,實(shí)現(xiàn)方式是通過Thread.sleep(sleepTime)來實(shí)現(xiàn)罕容;不過這也給了我們極大的發(fā)揮空間,我們可以自己實(shí)現(xiàn)阻塞策略稿饰。

4. AttemptTimeLimiters 任務(wù)執(zhí)行時(shí)長(zhǎng)限制

這個(gè)表示單次任務(wù)執(zhí)行時(shí)間限制(如果單次任務(wù)執(zhí)行超時(shí)锦秒,則終止執(zhí)行當(dāng)前任務(wù));

4.1 NoAttemptTimeLimit 無時(shí)長(zhǎng)限制
.withAttemptTimeLimiter(AttemptTimeLimiters.noTimeLimit())

顧名思義喉镰,不限制執(zhí)行時(shí)長(zhǎng)旅择;每次都是等執(zhí)行任務(wù)執(zhí)行完成之后,才進(jìn)行后續(xù)的重試策咯侣姆。


4.2 FixedAttemptTimeLimit
.withAttemptTimeLimiter(AttemptTimeLimiters.fixedTimeLimit(10, TimeUnit.SECONDS));
.withAttemptTimeLimiter(AttemptTimeLimiters.fixedTimeLimit(10, TimeUnit.SECONDS, Executors.newCachedThreadPool()));

可以指定任務(wù)的執(zhí)行時(shí)長(zhǎng)限制生真,并且為了控制線程管理,最好指定相應(yīng)的線程池捺宗。

轉(zhuǎn)自:http://www.reibang.com/p/a289dde63043

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末柱蟀,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子蚜厉,更是在濱河造成了極大的恐慌长已,老刑警劉巖,帶你破解...
    沈念sama閱讀 210,978評(píng)論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件弯囊,死亡現(xiàn)場(chǎng)離奇詭異痰哨,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)匾嘱,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 89,954評(píng)論 2 384
  • 文/潘曉璐 我一進(jìn)店門斤斧,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人霎烙,你說我怎么就攤上這事撬讽。” “怎么了悬垃?”我有些...
    開封第一講書人閱讀 156,623評(píng)論 0 345
  • 文/不壞的土叔 我叫張陵游昼,是天一觀的道長(zhǎng)。 經(jīng)常有香客問我尝蠕,道長(zhǎng)烘豌,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 56,324評(píng)論 1 282
  • 正文 為了忘掉前任看彼,我火速辦了婚禮廊佩,結(jié)果婚禮上囚聚,老公的妹妹穿的比我還像新娘。我一直安慰自己标锄,他們只是感情好顽铸,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,390評(píng)論 5 384
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著料皇,像睡著了一般谓松。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上践剂,一...
    開封第一講書人閱讀 49,741評(píng)論 1 289
  • 那天鬼譬,我揣著相機(jī)與錄音,去河邊找鬼舷手。 笑死拧簸,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的男窟。 我是一名探鬼主播盆赤,決...
    沈念sama閱讀 38,892評(píng)論 3 405
  • 文/蒼蘭香墨 我猛地睜開眼,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼歉眷!你這毒婦竟也來了牺六?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,655評(píng)論 0 266
  • 序言:老撾萬榮一對(duì)情侶失蹤汗捡,失蹤者是張志新(化名)和其女友劉穎淑际,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體扇住,經(jīng)...
    沈念sama閱讀 44,104評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡春缕,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,451評(píng)論 2 325
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了艘蹋。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片锄贼。...
    茶點(diǎn)故事閱讀 38,569評(píng)論 1 340
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖女阀,靈堂內(nèi)的尸體忽然破棺而出宅荤,到底是詐尸還是另有隱情,我是刑警寧澤浸策,帶...
    沈念sama閱讀 34,254評(píng)論 4 328
  • 正文 年R本政府宣布冯键,位于F島的核電站,受9級(jí)特大地震影響庸汗,放射性物質(zhì)發(fā)生泄漏惫确。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,834評(píng)論 3 312
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望雕薪。 院中可真熱鬧昧诱,春花似錦、人聲如沸所袁。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,725評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽燥爷。三九已至,卻和暖如春懦窘,著一層夾襖步出監(jiān)牢的瞬間前翎,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,950評(píng)論 1 264
  • 我被黑心中介騙來泰國打工畅涂, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留港华,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 46,260評(píng)論 2 360
  • 正文 我出身青樓午衰,卻偏偏與公主長(zhǎng)得像立宜,于是被迫代替她去往敵國和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子臊岸,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,446評(píng)論 2 348

推薦閱讀更多精彩內(nèi)容

  • 一橙数、前言 由于最近項(xiàng)目中用到了guava-retrying,并且以前沒有遇到過這個(gè)工具包帅戒,所以準(zhǔn)備通過本篇文章來系...
    騎著烏龜去看海閱讀 6,015評(píng)論 0 3
  • 業(yè)務(wù)開發(fā)中為了保證銜接模塊的偶爾不確定性,需要做一些重試保障機(jī)制. 為了讓我們的重試代碼更優(yōu)雅簡(jiǎn)單, 這里介紹兩個(gè)...
    林昀熙閱讀 862評(píng)論 0 0
  • 一灯帮、使用場(chǎng)景 在日常開發(fā)中,我們經(jīng)常會(huì)遇到需要調(diào)用外部服務(wù)和接口的場(chǎng)景逻住。外部服務(wù)對(duì)于調(diào)用者來說一般都是不可靠的钟哥,尤...
    端木軒閱讀 5,262評(píng)論 3 22
  • 1. 說明 最近公司在搞活動(dòng),需要依賴一個(gè)第三方接口瞎访,測(cè)試階段并沒有什么異常狀況腻贰,但上線后發(fā)現(xiàn)依賴的接口有時(shí)候會(huì)因...
    Java_Explorer閱讀 1,035評(píng)論 0 0
  • 久違的晴天,家長(zhǎng)會(huì)装诡。 家長(zhǎng)大會(huì)開好到教室時(shí)银受,離放學(xué)已經(jīng)沒多少時(shí)間了。班主任說已經(jīng)安排了三個(gè)家長(zhǎng)分享經(jīng)驗(yàn)鸦采。 放學(xué)鈴聲...
    飄雪兒5閱讀 7,513評(píng)論 16 22