Hystrix熔断的方法级别(自定义commonKey)

一、Hystrix的Feign熔断的粒度

Feign可以直接去集成Hystrix熔断,那么默认的熔断粒度是多大呢?或者说,当serviceA调用serviceB#method1(param)时,如果出现超时导致熔断后,serviceA还能不能调用serviceB#method2(param)呢?

我做了一个模拟测试,当serviceA调用serviceB#method1(param)时,报错信息如下:

com.netflix.hystrix.exception.HystrixRuntimeException: serviceB#method1(param) short-circuited and no fallback available.

at com.netflix.hystrix.AbstractCommand$22.call(AbstractCommand.java:819)

当serviceA调用serviceB#method2(param)时,请求和返回都是正常的。

结论:Hystrix熔断的粒度是方法层面的。

根据上面的报错的AbstractCommand.java:819跟进到源码中:

     toEmit = new HystrixRuntimeException(failureType, _cmd.getClass(), getLogMessagePrefix() + " " + message + " and no fallback available.", e, fe);

    //serviceB#method1(param)的来源   
    protected String getLogMessagePrefix() {
        return getCommandKey().name();
    }
 
    //
    public HystrixCommandKey getCommandKey() {
        return commandKey;
    }
    //group默认是服务名称
    this.commandGroup = initGroupKey(group);
    //key默认是feignclient的类名#method(参数名称)
    this.commandKey = initCommandKey(key, getClass());

    //
    private static HystrixCommandKey initCommandKey(final HystrixCommandKey fromConstructor, Class<?> clazz) {
        if (fromConstructor == null || fromConstructor.name().trim().equals("")) {
            final String keyName = getDefaultNameFromClass(clazz);
            return HystrixCommandKey.Factory.asKey(keyName);
        } else {
            return fromConstructor;
        }
    }

也就是说熔断的粒度是FeignClient类下的方法层面。 

 

二、自定义熔断的范围

Feign-灵活的使用Hystrix熔断(自定义CommandKey)

但是配置时,却不是很灵活,只是支持default类名#方法名()的配置。这就不能对类或者一组方法进行统一的配置。

 

源码改造:

@Configuration
public class MyHystrixFeign {

    @Bean
    @Scope("prototype")
    @ConditionalOnProperty(name = "feign.hystrix.enabled")
    public Feign.Builder feignHystrixBuilder() {
        return HystrixFeign.builder().setterFactory(new MyDefault());
    }

    /**
     * 修改源码{@link HystrixFeign.Builder#setterFactory}
     */
    final class MyDefault implements SetterFactory {

        @Override
        public HystrixCommand.Setter create(Target<?> target, Method method) {
       
            String groupKey = target.name();
            String commandKey = Feign.configKey(target.type(), method);
            //
            if ("TestDemoApi1".equals(target.type().getSimpleName())) {
                return HystrixCommand.Setter
                        .withGroupKey(HystrixCommandGroupKey.Factory.asKey(groupKey))
                        .andCommandKey(HystrixCommandKey.Factory.asKey("TestDemoApi1"))
                        .andThreadPoolKey(HystrixThreadPoolKey.Factory.asKey(commandKey));
            }
            return HystrixCommand.Setter
                    .withGroupKey(HystrixCommandGroupKey.Factory.asKey(groupKey))
                    .andCommandKey(HystrixCommandKey.Factory.asKey(commandKey));
        }
    }

}

 

项目启动后,会遍历@Feign注解类中的每一个方法调用create生成Hystrix的配置key,也可以是线程池的key。
源码位置:feign.hystrix.HystrixInvocationHandler#toSetters如下图所示。

  /**
   * Process all methods in the target so that appropriate setters are created.
   * 为每一个方法增加熔断的配置(可以在代码中配置,也可以在yml中进行配置)。
   */
  static Map<Method, Setter> toSetters(SetterFactory setterFactory, Target<?> target,
                                       Set<Method> methods) {
    Map<Method, Setter> result = new LinkedHashMap<Method, Setter>();
    for (Method method : methods) {
      method.setAccessible(true);
      //扩展的是这个方法(由用户自己定义配置)。
      result.put(method, setterFactory.create(target, method));
    }
    return result;
  }

 

yml的配置:

feign:
  # Dalston SR1(待定)之后的版本默认关闭hystrix对feign的支持,如果想要使用fallback功能这里必须启用。
  hystrix:
    enabled: true
#
#
#hystrix:
#  command:
#    default:
#      execution:
#        isolation:
#          thread:
#            timeoutInMilliseconds: 100000  # 调用者执行的超时时间默认是1s
#  threadpool:
#    default:
#      coreSize: 1 #核心线程数
#      maximumSize: 1 # 最大线程数
#      maxQueueSize: 0 # 不使用队列
#

## Feign仅仅支持方法级别和default级别
hystrix:
  command:
    TestDemoApi1:   ## 支持类级别
     execution:
      isolation:
       thread:
        timeoutInMilliseconds: 4000  # 调用者执行的超时时间默认是1s

 

注:默认情况下,Feign-Hystrix会使用服务名作为CommandGroup,使用类名#方法名作为CommandKey。

而在yml配置:全局配置是default的配置,而实例配置为commandKey配置。

更多的配置,可以参考Hystrix(2)— 相关配置

 

 



参考:https://www.jianshu.com/p/58f6e180999f
https://blog.csdn.net/weixin_42047790/article/details/108024957

https://blog.csdn.net/weixin_39660224/article/details/109477040

posted on 2021-03-30 17:33  duanxz  阅读(1509)  评论(0编辑  收藏  举报