美文网首页Spring Cloud
Hystrix 超时配置的N种玩法

Hystrix 超时配置的N种玩法

作者: 尹吉欢 | 来源:发表于2019-05-28 21:24 被阅读8次

    前阵子在我的知识星球中,有位朋友对我提了个问题,问我如何让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调用的时候,只能支持一种超时配置,要么默认的接口级别,要么自定义的服务级别。那么有没有什么方式能够让两种同时支持呢?

    欢迎加入我的知识星球,一起交流技术,免费学习猿天地的课程(http://cxytiandi.com/course

    PS:目前星球中正在星主的带领下组队学习Spring Cloud,等你哦!

    微信扫码加入猿天地知识星球 猿天地

    相关文章

      网友评论

        本文标题:Hystrix 超时配置的N种玩法

        本文链接:https://www.haomeiwen.com/subject/amzxaqtx.html