SpringCloud Fegin超時重試源碼

springCloud中最重要的就是微服務(wù)之間的調(diào)用放刨,因?yàn)榫W(wǎng)絡(luò)延遲或者調(diào)用超時會直接導(dǎo)致程序異常舀瓢,因此超時的配置及處理就至關(guān)重要躲叼。

在開發(fā)過程中被調(diào)用的微服務(wù)打斷點(diǎn)發(fā)現(xiàn)會又多次重試的情況则果,測試環(huán)境有的請求響應(yīng)時間過長也會出現(xiàn)多次請求,網(wǎng)上查詢了配置試了一下無果凭疮,決定自己看看源碼。
本人使用的SpringCloud版本是Camden.SR3串述。

微服務(wù)間調(diào)用其實(shí)走的是http請求执解,debug了一下默認(rèn)的ReadTimeout時間為5s,ConnectTimeout時間為2s纲酗,我使用的是Fegin進(jìn)行微服務(wù)間調(diào)用衰腌,底層用的還是Ribbon,網(wǎng)上提到的配置如下

ribbon:
  ReadTimeout: 60000
  ConnectTimeout: 60000
  MaxAutoRetries: 0
  MaxAutoRetriesNextServer: 1

超時時間是有效的但是重試的次數(shù)無效觅赊,如果直接使用ribbon應(yīng)該是有效的右蕊。

下面開始測試:
在微服務(wù)B中建立測試方法,sleep 8s 確保請求超時

    public Integer testee(){
        try {
            Thread.sleep(8000L);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        return 9;
    }

在微服務(wù)A中使用fegin調(diào)用此方法時看到有異常

看到在SynchronousMethodHandler中請求的方法

    Request request = targetRequest(template);
    if (logLevel != Logger.Level.NONE) {
      logger.logRequest(metadata.configKey(), logLevel, request);
    }
    Response response;
    long start = System.nanoTime();
    try {
      response = client.execute(request, options);
      response.toBuilder().request(request).build();
    } catch (IOException e) {
      if (logLevel != Logger.Level.NONE) {
        logger.logIOException(metadata.configKey(), logLevel, e, elapsedTime(start));
      }
     //出現(xiàn)異常后拋出RetryableException
      throw errorExecuting(request, e);
    }

出現(xiàn)異常后調(diào)用 throw errorExecuting(request, e) 拋出異常

在調(diào)用executeAndDecode的地方catch

@Override
  public Object invoke(Object[] argv) throws Throwable {
    RequestTemplate template = buildTemplateFromArgs.create(argv);
    Retryer retryer = this.retryer.clone();
    while (true) {
      try {
        return executeAndDecode(template);
      } catch (RetryableException e) {
         //重試的地方
        retryer.continueOrPropagate(e);
        if (logLevel != Logger.Level.NONE) {
          logger.logRetry(metadata.configKey(), logLevel);
        }
        continue;
      }
    }
  }

retryer.continueOrPropagate(e); 這句就是關(guān)鍵繼續(xù)跟進(jìn)

public void continueOrPropagate(RetryableException e) {
        //maxAttempts是構(gòu)造方法傳進(jìn)來的大于重試次數(shù)拋出異常,否則繼續(xù)循環(huán)執(zhí)行請求
      if (attempt++ >= maxAttempts) {
        throw e;
      }
     ....

默認(rèn)的Retryer構(gòu)造器

 public Default() {
      this(100, SECONDS.toMillis(1), 5);
    }

第一個參數(shù)period是請求重試的間隔算法參數(shù)吮螺,第二個參數(shù)maxPeriod 是請求間隔最大時間饶囚,第三個參數(shù)是重試的次數(shù)。算法如下:

      long interval = (long) (period * Math.pow(1.5, attempt - 1));
      return interval > maxPeriod ? maxPeriod : interval;
    }

我們能否改寫參數(shù)呢鸠补?我們再看看SpringCloud的文檔中關(guān)于Retry的配置


新建一個配置類

@Configuration
public class FeginConfig {
    @Bean
    public Retryer feginRetryer(){
        Retryer retryer = new Retryer.Default(100, SECONDS.toMillis(10), 3);
        return retryer;
    }
}

在feginClient是加入configuration的配置

@FeignClient(value = "fund-server",fallback = FundClientHystrix.class,configuration = FeginConfig.class)
public interface FundClient 

重啟重試萝风,只調(diào)用了一次,F(xiàn)egin重試次數(shù)解決紫岩。
我們再看看請求超時這里的參數(shù)

@Override
    public Response execute(Request request, Request.Options options) throws IOException {
        try {
            URI asUri = URI.create(request.url());
            String clientName = asUri.getHost();
            URI uriWithoutHost = cleanUrl(request.url(), clientName);
            FeignLoadBalancer.RibbonRequest ribbonRequest = new FeignLoadBalancer.RibbonRequest(
                    this.delegate, request, uriWithoutHost);
                     //請求參數(shù)
            IClientConfig requestConfig = getClientConfig(options, clientName);
            return lbClient(clientName).executeWithLoadBalancer(ribbonRequest,
                    requestConfig).toResponse();
        }
        catch (ClientException e) {
            IOException io = findIOException(e);
            if (io != null) {
                throw io;
            }
            throw new RuntimeException(e);
        }
    }

其中ReadTimeout 和 ConnectTimeout 讀取的就是ribbon的配置闹丐,再來看一眼

ribbon:
  ReadTimeout: 60000
  ConnectTimeout: 60000
  MaxAutoRetries: 0
  MaxAutoRetriesNextServer: 1

如果想覆蓋ribbon的超時設(shè)置可以在剛剛寫的FeginConfig里注入下面的bean

    public Request.Options feginOption(){
        Request.Options option = new Request.Options(7000,7000);
        return option;
    }

總結(jié):使用開源的東西在弄不清問題出在哪時最好能看看源碼,對原理的實(shí)現(xiàn)以及自己的編碼思路都有很大的提升被因。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末卿拴,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子梨与,更是在濱河造成了極大的恐慌堕花,老刑警劉巖,帶你破解...
    沈念sama閱讀 211,639評論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件粥鞋,死亡現(xiàn)場離奇詭異缘挽,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,277評論 3 385
  • 文/潘曉璐 我一進(jìn)店門壕曼,熙熙樓的掌柜王于貴愁眉苦臉地迎上來苏研,“玉大人,你說我怎么就攤上這事腮郊∧∧ⅲ” “怎么了?”我有些...
    開封第一講書人閱讀 157,221評論 0 348
  • 文/不壞的土叔 我叫張陵轧飞,是天一觀的道長衅鹿。 經(jīng)常有香客問我,道長过咬,這世上最難降的妖魔是什么大渤? 我笑而不...
    開封第一講書人閱讀 56,474評論 1 283
  • 正文 為了忘掉前任,我火速辦了婚禮掸绞,結(jié)果婚禮上泵三,老公的妹妹穿的比我還像新娘。我一直安慰自己衔掸,他們只是感情好切黔,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,570評論 6 386
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著具篇,像睡著了一般纬霞。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上驱显,一...
    開封第一講書人閱讀 49,816評論 1 290
  • 那天诗芜,我揣著相機(jī)與錄音,去河邊找鬼埃疫。 笑死伏恐,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的栓霜。 我是一名探鬼主播翠桦,決...
    沈念sama閱讀 38,957評論 3 408
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼胳蛮!你這毒婦竟也來了销凑?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,718評論 0 266
  • 序言:老撾萬榮一對情侶失蹤仅炊,失蹤者是張志新(化名)和其女友劉穎斗幼,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體抚垄,經(jīng)...
    沈念sama閱讀 44,176評論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡蜕窿,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,511評論 2 327
  • 正文 我和宋清朗相戀三年谋逻,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片桐经。...
    茶點(diǎn)故事閱讀 38,646評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡毁兆,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出阴挣,到底是詐尸還是另有隱情气堕,我是刑警寧澤,帶...
    沈念sama閱讀 34,322評論 4 330
  • 正文 年R本政府宣布屯吊,位于F島的核電站送巡,受9級特大地震影響摹菠,放射性物質(zhì)發(fā)生泄漏盒卸。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,934評論 3 313
  • 文/蒙蒙 一次氨、第九天 我趴在偏房一處隱蔽的房頂上張望蔽介。 院中可真熱鬧,春花似錦煮寡、人聲如沸虹蓄。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,755評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽薇组。三九已至,卻和暖如春坐儿,著一層夾襖步出監(jiān)牢的瞬間律胀,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,987評論 1 266
  • 我被黑心中介騙來泰國打工貌矿, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留炭菌,地道東北人。 一個月前我還...
    沈念sama閱讀 46,358評論 2 360
  • 正文 我出身青樓逛漫,卻偏偏與公主長得像黑低,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子酌毡,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,514評論 2 348

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