前阵子在个人知识星球中,有位朋友对我提了个问题,问我如何让Hystrix支持对接口级别的超时配置,今天给你们写篇文章,普及下Hystrix配置超时的几种方式。spring
至于之后你是用阿里的Sentinel仍是Netflix Hystrix我就无论了,但今天的主题仍是Netflix Hystrix,至少目前仍是有不少在使用的,因此今天这篇文章仍是看看吧。apache
若是咱们使用的是@HystrixCommand注解,那么能够在注解中直接指定超时时间,以下:bash
@HystrixCommand(fallbackMethod="fallback",
commandProperties = {
@HystrixProperty(name = "execution.isolation.thread.timeoutInMilliseconds", value = "1000" )
}
)
复制代码
固然也能够指定commandKey,而后在配置文件中配置超时时间,以下:app
@HystrixCommand(fallbackMethod="fallback",commandKey="userGetKey")
复制代码
配置文件给commandKey配置超时时间:ide
hystrix.command.userGetKey.execution.isolation.thread.timeoutInMilliseconds = 13000
复制代码
若是只是想全局的配置,能够配置默认的超时时间:函数
hystrix.command.default.execution.isolation.thread.timeoutInMilliseconds=3000
复制代码
假如咱们的Feign Client定义以下:源码分析
@FeignClient(value = "user-service", fallbackFactory = UserRemoteClientFallbackFactory.class)
public interface UserRemoteClient {
@GetMapping("/user/get")
public ResponseData<UserDto> getUser(@RequestParam("id") Long id);
}
复制代码
那么配置以下:ui
hystrix.command.UserRemoteClient#getUser(Long).execution.isolation.thread.timeoutInMilliseconds = 300
复制代码
为何要配置成上面的方式呢?this
其实就是对commandKey进行配置,只要咱们知道commandKey的生成规则就能够对接口级别进行配置,接口级别的规则是 Client名称#方法名(参数类型)spa
源码在feign.hystrix.SetterFactory.Default中:
String commandKey = Feign.configKey(target.type(), method);
复制代码
hystrix.command.service-id.execution.isolation.thread.timeoutInMilliseconds=3000
复制代码
Zuul中之因此要配置service-id缘由是commandKey就是用的service-id, 经过源码分析能够获得结论。
首先进入的是RibbonRoutingFilter中的run方法,而后咱们看核心的forward方法:
ClientHttpResponse response = forward(commandContext);
复制代码
在forward中有下面的代码:
RibbonCommand command = this.ribbonCommandFactory.create(context);
复制代码
经过create能够定位到具体的实现,这边就看你用的什么Http客户端,默认有三种实现,默认定位到org.springframework.cloud.netflix.zuul.filters.route.apache.HttpClientRibbonCommandFactory.create(RibbonCommandContext)方法。
重点在new HttpClientRibbonCommand这行代码,第一个参数就是serviceId,咱们看下HttpClientRibbonCommand构造函数的完整参数:
因此service-id就是commandKey。
@Bean
@Scope("prototype")
@ConditionalOnMissingBean
@ConditionalOnProperty(name = "feign.hystrix.enabled")
public Feign.Builder feignHystrixBuilder() {
return HystrixFeign.builder().setterFactory(new SetterFactory() {
@Override
public Setter create(Target<?> target, Method method) {
String groupKey = target.name();
String commandKey = Feign.configKey(target.type(), method);
return HystrixCommand.Setter.withGroupKey(HystrixCommandGroupKey.Factory.asKey(groupKey))
//.andCommandKey(HystrixCommandKey.Factory.asKey(commandKey))
//.andCommandKey(HystrixCommandKey.Factory.asKey(groupKey))
.andCommandKey(HystrixCommandKey.Factory.asKey(target.type().getSimpleName()));
}
});
}
复制代码
.andCommandKey(HystrixCommandKey.Factory.asKey(commandKey)) 默认的接口方式
.andCommandKey(HystrixCommandKey.Factory.asKey(groupKey)) service-id方式
.andCommandKey(HystrixCommandKey.Factory.asKey(target.type().getSimpleName())); Feign Client Name方式
配置的话根据不一样的配置填写不通的commandKey就能够了:
hystrix.command.Feign Client Name.execution.isolation.thread.timeoutInMilliseconds=3000
复制代码
留一个问题你们思考下,欢迎留言讨论:
若是咱们定制commandKey,也就意味着在使用Feign调用的时候,只能支持一种超时配置,要么默认的接口级别,要么自定义的服务级别。那么有没有什么方式可以让两种同时支持呢?