Hystrix 超時配置的N種玩法


前陣子在我的知識星球中,有位朋友對我提了個問題,問我如何讓Hystrix支持對接口級別的超時配置,今天給大家寫篇文章,普及下Hystrix配置超時的幾種方式。

至於以后你是用阿里的Sentinel還是Netflix Hystrix我就不管了,但今天的主題還是Netflix Hystrix,至少目前還是有很多在使用的,所以今天這篇文章還是看看吧。

@HystrixCommand

如果我們使用的是@HystrixCommand注解,那么可以在注解中直接指定超時時間,如下:

@HystrixCommand(fallbackMethod="fallback",
	commandProperties = {
	     @HystrixProperty(name = "execution.isolation.thread.timeoutInMilliseconds", value = "1000" )
	}
)

當然也可以指定commandKey,然后在配置文件中配置超時時間,如下:

@HystrixCommand(fallbackMethod="fallback",commandKey="userGetKey")

配置文件給commandKey配置超時時間:

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);
	
}

那么配置如下:

hystrix.command.UserRemoteClient#getUser(Long).execution.isolation.thread.timeoutInMilliseconds = 300

為什么要配置成上面的方式呢?

其實就是對commandKey進行配置,只要我們知道commandKey的生成規則就可以對接口級別進行配置,接口級別的規則是 Client名稱#方法名(參數類型)

源碼在feign.hystrix.SetterFactory.Default中:

String commandKey = Feign.configKey(target.type(), method);

服務級別配置

1.在Zuul中針對服務級別的話,直接配置service-id,如下:
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。

2.在Feign中針對服務級別的話,需要對commandKey進行定制,可以用service-id, 也可以用Feign Client Name,如下:
@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調用的時候,只能支持一種超時配置,要么默認的接口級別,要么自定義的服務級別。那么有沒有什么方式能夠讓兩種同時支持呢?

猿天地


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM