關(guān)于feign client觸發(fā)熔斷的異常

使用feign client進(jìn)行restful服務(wù)間的調(diào)用,除了要注意超時時間账锹、retry的設(shè)置外,還有一個關(guān)于自定義異常的部分坷襟,需要注意一下奸柬,不然容易出錯。

nginx對于upstream的health check

Nginx 默認(rèn)判斷失敗節(jié)點(diǎn)狀態(tài)以connect refuse和time out狀態(tài)為準(zhǔn)婴程,不以HTTP錯誤狀態(tài)進(jìn)行判斷失敗廓奕,因為HTTP只要能返回狀態(tài)說明該節(jié)點(diǎn)還可以正常連接,所以nginx判斷其還是存活狀態(tài)档叔;除非添加了proxy_next_upstream指令設(shè)置對404桌粉、502、503衙四、504铃肯、500和time out等錯誤進(jìn)行轉(zhuǎn)到備機(jī)處理。

feign及hystrix對于服務(wù)提供方的health check

HystrixBadRequestException

這個異常主要是用來適配IllegalArgumentException這類異常传蹈。HystrixBadRequestException與其他HystrixCommand拋出的異常不同押逼,該異常不會納入circuit breaker的統(tǒng)計里頭,即不會觸發(fā)熔斷卡睦。

feign client對restful調(diào)用的異常處理

/Users/xixicat/.m2/repository/io/github/openfeign/feign-core/9.3.1/feign-core-9.3.1-sources.jar!/feign/SynchronousMethodHandler.java

Object executeAndDecode(RequestTemplate template) throws Throwable {
    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);
      // ensure the request is set. TODO: remove in Feign 10
      response.toBuilder().request(request).build();
    } catch (IOException e) {
      if (logLevel != Logger.Level.NONE) {
        logger.logIOException(metadata.configKey(), logLevel, e, elapsedTime(start));
      }
      throw errorExecuting(request, e);
    }
    long elapsedTime = TimeUnit.NANOSECONDS.toMillis(System.nanoTime() - start);

    boolean shouldClose = true;
    try {
      if (logLevel != Logger.Level.NONE) {
        response =
            logger.logAndRebufferResponse(metadata.configKey(), logLevel, response, elapsedTime);
        // ensure the request is set. TODO: remove in Feign 10
        response.toBuilder().request(request).build();
      }
      if (Response.class == metadata.returnType()) {
        if (response.body() == null) {
          return response;
        }
        if (response.body().length() == null ||
                response.body().length() > MAX_RESPONSE_BUFFER_SIZE) {
          shouldClose = false;
          return response;
        }
        // Ensure the response body is disconnected
        byte[] bodyData = Util.toByteArray(response.body().asInputStream());
        return response.toBuilder().body(bodyData).build();
      }
      if (response.status() >= 200 && response.status() < 300) {
        if (void.class == metadata.returnType()) {
          return null;
        } else {
          return decode(response);
        }
      } else if (decode404 && response.status() == 404) {
        return decoder.decode(response, metadata.returnType());
      } else {
        throw errorDecoder.decode(metadata.configKey(), response);
      }
    } catch (IOException e) {
      if (logLevel != Logger.Level.NONE) {
        logger.logIOException(metadata.configKey(), logLevel, e, elapsedTime);
      }
      throw errorReading(request, response, e);
    } finally {
      if (shouldClose) {
        ensureClosed(response.body());
      }
    }
  }

其中對status code的處理見這段

     if (response.status() >= 200 && response.status() < 300) {
        if (void.class == metadata.returnType()) {
          return null;
        } else {
          return decode(response);
        }
      } else if (decode404 && response.status() == 404) {
        return decoder.decode(response, metadata.returnType());
      } else {
        throw errorDecoder.decode(metadata.configKey(), response);
      }

也就是feign client的處理跟nginx的是不一樣的宴胧,feign client把非200的以及404(可以配置是否納入異常)都算成error,都轉(zhuǎn)給errorDecoder去處理了表锻。

小結(jié)

要特別注意恕齐,對于restful拋出的4xx的錯誤,也許大部分是業(yè)務(wù)異常,并不是服務(wù)提供方的異常显歧,因此在進(jìn)行feign client調(diào)用的時候仪或,需要進(jìn)行errorDecoder去處理,適配為HystrixBadRequestException士骤,好避開circuit breaker的統(tǒng)計范删,否則就容易誤判,傳幾個錯誤的參數(shù)拷肌,立馬就熔斷整個服務(wù)了到旦,后果不堪設(shè)想。

  • 附errorDecoder實(shí)例
@Configuration
public class BizExceptionFeignErrorDecoder implements feign.codec.ErrorDecoder{

    private static final Logger logger = LoggerFactory.getLogger(BizExceptionFeignErrorDecoder.class);

    @Override
    public Exception decode(String methodKey, Response response) {
        if(response.status() >= 400 && response.status() <= 499){
            return new HystrixBadRequestException("xxxxxx");
        }
        return feign.FeignException.errorStatus(methodKey, response);
    }
}

doc

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末巨缘,一起剝皮案震驚了整個濱河市添忘,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌若锁,老刑警劉巖搁骑,帶你破解...
    沈念sama閱讀 218,755評論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異又固,居然都是意外死亡仲器,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,305評論 3 395
  • 文/潘曉璐 我一進(jìn)店門仰冠,熙熙樓的掌柜王于貴愁眉苦臉地迎上來乏冀,“玉大人,你說我怎么就攤上這事洋只∶罕妫” “怎么了?”我有些...
    開封第一講書人閱讀 165,138評論 0 355
  • 文/不壞的土叔 我叫張陵木张,是天一觀的道長众辨。 經(jīng)常有香客問我,道長舷礼,這世上最難降的妖魔是什么鹃彻? 我笑而不...
    開封第一講書人閱讀 58,791評論 1 295
  • 正文 為了忘掉前任,我火速辦了婚禮妻献,結(jié)果婚禮上蛛株,老公的妹妹穿的比我還像新娘。我一直安慰自己育拨,他們只是感情好谨履,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,794評論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著熬丧,像睡著了一般笋粟。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,631評論 1 305
  • 那天害捕,我揣著相機(jī)與錄音绿淋,去河邊找鬼。 笑死尝盼,一個胖子當(dāng)著我的面吹牛吞滞,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播盾沫,決...
    沈念sama閱讀 40,362評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼裁赠,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了赴精?” 一聲冷哼從身側(cè)響起组贺,我...
    開封第一講書人閱讀 39,264評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎祖娘,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體啊奄,經(jīng)...
    沈念sama閱讀 45,724評論 1 315
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡渐苏,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,900評論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了菇夸。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片琼富。...
    茶點(diǎn)故事閱讀 40,040評論 1 350
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖庄新,靈堂內(nèi)的尸體忽然破棺而出鞠眉,到底是詐尸還是另有隱情,我是刑警寧澤择诈,帶...
    沈念sama閱讀 35,742評論 5 346
  • 正文 年R本政府宣布械蹋,位于F島的核電站,受9級特大地震影響羞芍,放射性物質(zhì)發(fā)生泄漏哗戈。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,364評論 3 330
  • 文/蒙蒙 一荷科、第九天 我趴在偏房一處隱蔽的房頂上張望唯咬。 院中可真熱鬧,春花似錦畏浆、人聲如沸胆胰。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,944評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽蜀涨。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間勉盅,已是汗流浹背佑颇。 一陣腳步聲響...
    開封第一講書人閱讀 33,060評論 1 270
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留草娜,地道東北人挑胸。 一個月前我還...
    沈念sama閱讀 48,247評論 3 371
  • 正文 我出身青樓,卻偏偏與公主長得像宰闰,于是被迫代替她去往敵國和親茬贵。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,979評論 2 355

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

  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見模式的工具(例如配置管理移袍,服務(wù)發(fā)現(xiàn)解藻,斷路器,智...
    卡卡羅2017閱讀 134,659評論 18 139
  • 第一章 Nginx簡介 Nginx是什么 沒有聽過Nginx葡盗?那么一定聽過它的“同行”Apache吧螟左!Ngi...
    JokerW閱讀 32,687評論 24 1,002
  • 1. Nginx的模塊與工作原理 Nginx由內(nèi)核和模塊組成,其中觅够,內(nèi)核的設(shè)計非常微小和簡潔胶背,完成的工作也非常簡單...
    rosekissyou閱讀 10,215評論 5 124
  • Page 1:nginx 服務(wù)器安裝及配置文件詳解 CentOS 6.2 x86_64 安裝 nginx 1.1 ...
    xiaojianxu閱讀 8,539評論 1 41
  • 異常 upstream server temporarily disabled while connecting ...
    go4it閱讀 24,690評論 0 0