Hystrix配置实战及feign超时配置失效

一、feign超时配置失效

最近项目上遇见feign超时配置总是失效。导致feign调用超过2s之后就会超时,会进行自动重试,重复调用两次服务,并且还是指定接口。这就更加奇怪。最后通过观察以及源码调试,发现问题所在。在这里先说下原因。

 

原因:同一个服务feign组件做了拆分,使用contextId对feign拆分后的feign做了声明。配置超时配置的时候,不能再使用feign组件注解 @FeignClient里的name去做配置了,而应该是contextId里的名称

示例代码:

//A服务的基础业务接口
@FeignClient(contextId = "AServer", name = "AServer", configuration = FeignConfiguration.class)
public interface ABaseServer {

}

//A服务的个性化业务接口
@FeignClient(contextId = "ASpecialServiceServer", name = "AServer", configuration = FeignConfiguration.class)
public interface ASpecialServer {

}

//上面是对feign拆分后的声明
//错误的yml配置
feign:
  client:
    config:
#这里仍然使用了name作为超时配置,那么只有ABaseServer 里面声明的接口才会使用以下的配置,因为恰巧ABaseServer的contextId名称是AServer。
      AServer: 
        connectTimeout: 60000
        readTimeout: 60000

//正确的yml配置,手段一:配置上以contextId为声明来配置
feign:
  client:
    config:
#基础业务接口的超时配置
      AServer: 
        connectTimeout: 60000
        readTimeout: 60000
#个性化业务接口的超时配置
      ASpecialServiceServer: 
        connectTimeout: 50000
        readTimeout: 50000

//正确的yml配置,手段二:A服务全部使用default全局配置,Bserver单独声明,并不会使用全局配置
feign:
  client:
    config:
      default: 
        connectTimeout: 60000
        readTimeout: 60000
      BServer:
        connectTimeout: 30000
        readTimeout: 30000

feign内部集成了ribbon做为了负载均衡的组件,ribbon也有相关超时配置,feign的超时配置不当也会造成超时失效,关于如何配置可以参考之前的一篇博客:https://www.cnblogs.com/wa1l-E/p/13994240.html

这次feign的超时不生效,主要原因是,项目上做了一次feign的拆分,即A服务调用B服务的接口由于过多,接口从功能模块和业务上做了feign组件的拆分,也就是spring容器中会有两个feign针对同一个服务。

问题1:拆分后,springboot在启动时,会报错,原因是针对同一个服务有多个feign 实例,而spring容器又默认是单例加载。

解决这个问题有两个方案:

1、

 

2、在feign注解定义上加上contextId来避免启动报错。示例代码如下:

@FeignClient(name = "A", contextId = "ABaseServiceServer", configuration = FeignConfiguration.class)
public interface AServer {

}


@FeignClient(name = "A", contextId = "ACustomServiceServer", configuration = FeignConfiguration.class)
public interface AServer {

}

都是同一个服务的feign组件,但是contextId不同,解决了问题。

项目上采用了第二种解决手段,但也正是因为对解决问题没有做到追根刨底的精神,导致引入了feign超时失效的原因。

问题2:使用ContextId对feign做声明后,导致部分接口超时失效。

结论:在开篇时,结论已经说过,这里就不再赘述。主要说下原因以及定位问题的过程和解决方法。

定位过程:发现该问题时,首先发现是部分接口失效,当然是测试并观察,发现只有未使用contextId配置的feign组件的接口会超时。但是当时并不知道是contextId的声明影响。所以果断开撕源码。定位问题

首先Feign有一个内部类Builder,听名字就知道使用了建造者是设计模式,建造者适合创造属性多变的对象, 而Feign恰好具备这种特性,使用建造者设计模式在适合不过了。

Builder类有一个属性Options option这个Options类就是feign的超时配置声明。如下图:

    再来看一下UML图

 

     可以看到真正的配置就是再容器初始话feign的时候,初始化 builder的时候使用的配置就是真正使用的配置。那么接下来就好办了,使用我之前讲过的源码调试大法,开始调试,启动服务,断点开启,最后一路追踪,发现实例化的代码如下:

     不知道启动后怎么调试找到相关代码的同学可以参考另一篇博客:https://www.cnblogs.com/wa1l-E/p/14115042.html    还是一句话,动手多实践。

    

    97行见名其义:初始化Feign.builder,109行是关键代码,看名字就知道,配置feign,那么builder的option一定是在这里初始化的,我们一路追进去看看

到了上面的方法中,我们发现了尤其重要的两行代码,看名字就知道使用configure配置属性,那么在这里一定是使用配置去初始话Feign的超时相关配置,没有的话会使用默认的配置。
这里的方法就不赘述了,有兴趣的同学可以去断点看看,最关键的另一个发现是 在获取配置的时候,使用的是
contextId,这不由得和上面Feign注解 @FeignClient中声明的contextId关联起来,最后通过调试也发现,确实是这样。contextId源码注释是bean的显实声明名称,如果不配置默认使用beanName.到这里就发现问题了。
那么解决手段就简单了

解决手段:

手段一:如果拆分后的接口不需要做特殊的超时配置区分,那么使用default全局配置既可,至于其他的feign客户端,在做配置,便不会使用全局的配置。

手段二:如果拆分后的接口,超时配置是不一样的,那么使用contextId做超时配置才是正确的。

最后建议实际使用手段二,粒度更细。

 

二、Hystrix配置实战:

首先介绍一下上面Feign超时后,Hystrix配置后,会自动重试的原因,然后再介绍一下Hystrix的主要配置,搭建一个Hstrix-dashboard,然后通过一个接口的测试,通过dashBoard观察Hystrix的配置的。

 1、Hystrix的配置

熔断配置:

#hystrix熔断器配置:(接口发生异常,服务调用方直接做熔断处理,返回提示,避免流量过大接口调用引起雪崩。)

#如果接口发生异常,那么会熔断,熔断开启。后面的请求不会再去进行服务远程调用,直接走熔断 #下面配置策略是: 10s滚动窗口期内,大于等于1个线程 失败率超过百分之50,则打开熔断开关.负责关闭熔断开关 #熔断开关打开后,后续请求直接走熔断,不会进行远程调用 hystrix.command.
default.circuitBreaker.requestVolumeThreshold=1 hystrix.command.default.metrics.rollingStats.timeInMilliseconds=10000 hystrix.command.default.circuitBreaker.errorThresholdPercentage=50 #在5s后,熔断会进入 半开状态,会放入一部分请求进行远程调用,如果成功,则关闭熔断.如果失败,则继续打开熔断 hystrix.command.default.circuitBreaker.sleepWindowInMilliseconds=5000

降级配置:

#hystrix降级配置:(接口发生异常,服务调用方直接对接口进行降级处理,返回托底数据。和熔断的区别是一个有托底数据,一个没有。)
#超时打开,设置为70s,这里的超时时间必须大于Ribbon和feign的超时,因为小于Feign正常调用超时时间,直接会熔断. hystrix.command.
default.execution.timeout.enabled=true hystrix.command.default.execution.isolation.thread.timeoutInMilliseconds=70000

 2、配置Hystrix-dashboard调试Hystrix熔断和降级配置

  • 搭建Hystrix-dashboard: 没空的同学可以直接下载我之前搭建的: https://github.com/coffeebabeCGG/spring-cloud 这里就不赘述如何搭建了
  • 启动项目后,需要填如要监控的服务地址:http://ip:port/context-path/actuator/hystrix.stream

  • 从下图可以看到queryByPage接口的熔断目前是关闭状态。关于dashboard的详细参数说明,下面给大家补一张图。

     

最后:接口postMan的runtest批量调用接口测试,通过dashBoard观察接口的熔断情况,配置是否生效。就可以了解Hystrix的基本使用了。

 

 

 

 

原文地址:https://www.cnblogs.com/wa1l-E/p/14814871.html