文档章节

关于feign client触发熔断的异常

go4it
 go4it
发布于 2017/02/11 23:47
字数 692
阅读 812
收藏 1

##序 使用feign client进行restful服务间的调用,除了要注意超时时间、retry的设置外,还有一个关于自定义异常的部分,需要注意一下,不然容易出错。

##nginx对于upstream的health check Nginx 默认判断失败节点状态以connect refuse和time out状态为准,不以HTTP错误状态进行判断失败,因为HTTP只要能返回状态说明该节点还可以正常连接,所以nginx判断其还是存活状态;除非添加了proxy_next_upstream指令设置对404、502、503、504、500和time out等错误进行转到备机处理。

##feign及hystrix对于服务提供方的health check ###HystrixBadRequestException 这个异常主要是用来适配IllegalArgumentException这类异常。HystrixBadRequestException与其他HystrixCommand抛出的异常不同,该异常不会纳入circuit breaker的统计里头,即不会触发熔断。 ###feign client对restful调用的异常处理 /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,都转给errorDecoder去处理了。

##小结 要特别注意,对于restful抛出的4xx的错误,也许大部分是业务异常,并不是服务提供方的异常,因此在进行feign client调用的时候,需要进行errorDecoder去处理,适配为HystrixBadRequestException,好避开circuit breaker的统计,否则就容易误判,传几个错误的参数,立马就熔断整个服务了,后果不堪设想。

  • 附errorDecoder实例
@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

© 著作权归作者所有

共有 人打赏支持
go4it
粉丝 76
博文 860
码字总数 756719
作品 0
深圳
私信 提问
白话SpringCloud | 第五章:服务容错保护(Hystrix)

前言 前一章节,我们知道了如何利用+和的方式进行服务的调用。在微服务架构中,一个服务可能会调用很多的其他微服务应用,虽然做了多集群部署,但可能还会存在诸如网络原因或者服务提供者自身...

oKong
2018/09/23
0
0
生产技巧:Feign如何控制Hystrix的启停、超时、熔断?

原文:http://www.itmuch.com/spring-cloud-sum/feign-hystrix/ ,转载请说明出处。 这也是一篇写于2017-08前后的工作日志,当时由于项目比较多,很多团队对Feign和Hystrix之间的小暧昧搞不清...

周立_ITMuch
2018/12/03
0
0
Spring Cloud Feign 异常处理

问题 最近在项目开发中,使用 Feign 调用服务,当触发熔断机制时,遇到了以下问题: 异常信息形如:; 获取不到服务提供方抛出的原始异常信息; 实现某些业务方法不进入熔断,直接往外抛出异...

xiaomin0322
2018/12/11
0
0
FeignClient超时配置

1前沿 使用Feign调用接口分两层,ribbon的调用和hystrix的调用,所以ribbon的超时时间和Hystrix的超时时间的结合就是Feign的超时时间 1.1ribbon配置 1.2 hystrix熔断配置 feignClient eureka...

lovelan1314
2018/12/14
0
0
[亲测]SpringCloud之熔断器Hystrix+实践

一.熔断器Hystrix 为什么要用熔断器 在高并发领域,在分布式系统中,可能因为一个小小的功能扛不住压力,宕机了,导致其他服务也跟随宕机,最终导致整个系统宕机,所以在SpringCloud中采用H...

Armymans
2018/12/10
0
0

没有更多内容

加载失败,请刷新页面

加载更多

大数据教程(11.9)hive操作基础知识

上一篇博客分享了hive的简介和初体验,本节博主将继续分享一些hive的操作的基础知识。 DDL操作 (1)创建表 #建表语法CREATE [EXTERNAL] TABLE [IF NOT EXISTS] table_name [(col_name ...

em_aaron
今天
0
0
OSChina 周四乱弹 —— 我家猫真会后空翻

Osc乱弹歌单(2019)请戳(这里) 【今日歌曲】 @我没有抓狂 :#今天听这个# 我艇牛逼,百听不厌,太好听辣 分享 Led Zeppelin 的歌曲《Stairway To Heaven》 《Stairway To Heaven》- Led Z...

小小编辑
今天
1
0
node调用dll

先安装python2.7 安装node-gyp cnpm install node-gyp -g 新建一个Electron-vue项目(案例用Electron-vue) vue init simulatedgreg/electron-vue my-project 安装electron-rebuild cnpm ins......

Chason-洪
今天
3
0
scala学习(一)

学习Spark之前需要学习Scala。 参考学习的书籍:快学Scala

柠檬果过
今天
3
0
通俗易懂解释网络工程中的技术,如STP,HSRP等

导读 在面试时,比如被问到HSRP的主备切换时间时多久,STP几个状态的停留时间,自己知道有这些东西,但在工作中不会经常用到,就老是记不住,觉得可能还是自己基础不够牢固,知识掌握不够全面...

问题终结者
昨天
4
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部