前陣子在個人知識星球中,有位朋友對我提了個問題,問我如何讓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調用的時候,只能支持一種超時配置,要麼默認的接口級別,要麼自定義的服務級別。那麼有沒有什麼方式可以讓兩種同時支持呢?