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