Hystrix

@HystrixCommand命令修饰的方法有2种执行方式:

1.同步:调用其他服务等待返回结果

2.异步:异步调用其他服务,返回Future对象,通过Future.get()获取返回结果。场景:当前服务需要调用多个其他服务然后汇总返回结果

---------------

服务降级

不用添加fallback服务降级方法的接口:

1.该接口返回类型为void,即不是查询类操作而是写操作,当写操作失败时要告诉调用者

2.接口执行批处理操作,报了异常不需要降级,只需要将异常返回给调用者就行

-----------------

命令分组、命令所属线程池

执行Hystrix命令默认使用的线程池是按照命令所在的分组划分的,一个命令分组公用一个线程池,在注解参数中指定分组,也可以更细粒度地指定所属线程池,如果指定了线程池,它的优先级更高,命令就不会用所在分组的默认线程池

配置方式:@HystrixCommand(fallbackMethod = "helloFallback", groupKey = "Group1", threadPoolKey = "HystrixFooServiceGaGa")

1.当上面3个属性都不配置的时候,比如study-spring-cloud-consumer中的HystrixUserService 这个类中所有标明了@HystrixCommand标的方法,都是使用1个线程池(线程名用的是类名hystrix-HystrixUserService-1 ),而如果有HystrixUserService2,里面也有@HystrixCommand标的方法,那么执行的时候使用的是另一个线程池,所以默认就已经是线程池隔离的

2.如果同时配置了groupKey 和 threadPoolKey ,那么具有相同的threadPoolKey的使用同一个线程池;

3.如果只配置了groupKey ,那么具有相同的groupKey 的使用同一个线程池;比如如果配置的是@HystrixCommand(fallbackMethod = "helloFallback", groupKey = "Group1"),那么线程名就是hystrix-Group1-*

-----------------

请求缓存

将命令请求获得的结果按照指定的key存储起来,key可以通过方法生成也可通过注解指定

    @CacheResult(cacheKeyMethod = "getUserCatchKey")
    @HystrixCommand
    public User getUserById(Long id) {
        return restTemplate.getForEntity("http://hello-provider/user", User.class).getBody();
    }

    public Long getUserCatchKey(Long id) {
        return id;
    }
方式一:指定key生成方法
    @CacheResult
    @HystrixCommand
    public User getUserById(@CacheKey("id") Long id) {
        return restTemplate.getForEntity("http://hello-provider/user", User.class).getBody();
    }
---------------
    @CacheResult
    @HystrixCommand
    public User getUserById(@CacheKey("id") User user) {// 自动获取user的id属性值
        return restTemplate.getForEntity("http://hello-provider/user", User.class).getBody();
    }
方式二:在方法参数中用@CacheKey指定

缓存清理

    @CacheResult
    @HystrixCommand
    public User getUserById(@CacheKey("id") Long id) {
        return restTemplate.getForEntity("http://hello-provider/user", User.class).getBody();
    }

    @CacheRemove(commandKey = "getUserById")
    @HystrixCommand
    public int update(@CacheKey("id") User user) {
        return restTemplate.postForEntity("http://hello-provider/user",user,Integer.class).getBody();
    }
@CacheRemove 在更新时设置缓存失效

--------------------

请求合并

在延时时间窗口10ms内,对同一个接口的多次请求合并成一个请求,底层是通过将多个请求的参数进行合并,变成一个请求,只占用线程池中的一条线程,前提是被调用服务要提供批量查询接口,比如getAll(List<Stirng> ids)

接收到回复后再做拆分响应给不同的请求

手写合并命令稍微麻烦点,要同时实现具体命令和合并器,参考P168

使用注解实现:

    @HystrixCollapser(batchMethod = "findAll", collapserProperties = {
            @HystrixProperty(name = "timeDelayInMilliseconds", value = "100") })
    @HystrixCommand
    public User find(Long id) {
        return null;
    }

    @HystrixCommand
    public List<User> findAll(List<Long> ids) {
        return restTemplate.getForEntity("http://hello-provider/users?ids={1}", List.class, StringUtils.join(ids, ","))
                .getBody();
    }
@HystrixCollapser

 ------------------

是否开启请求合并

请求合并有延迟时间窗,会造成请求延迟

1.若请求链路本身延迟较高,可开启请求合并,时间窗的10ms延迟可忽略不计了

2.若请求接口本身没什么并发量,不要开启

-------------------

仪表盘

 引入turbine构建监控聚集服务,将多个服务节点的信息进行汇总监控

还可在turbine前加入MQ,先将服务发送的监控信息-》MQ-》turbine异步消费汇总-》DashBoard仪表盘展示

--------------------

整体流程:

请求接口-》创建命令HystrixCommand-》触发命令执行-》命令结果是否被缓存-》(是,直接返回缓存结果)否-》断路器是否打开-》(是,走服务降级处理)否-》线程池是否有资源-》(否,走服务降级逻辑)是-》HystrixCommand.run()真正开始执行命令处理逻辑,调用服务提供者-》(如果超时,走服务降级逻辑)-》断路器统计命令执行情况(成功、失败、超时、拒绝)-》断路器维护10s内的统计时间窗,在此时间窗内若统计数据同时满足一下两个条件则打开断路器: “错误百分比超过50%”&&"请求总数超过20"-》断路器有5s休眠时间,5s内断路器状态是打开,期间的命令请求全部走服务降级逻辑,5s后断路器状态是半开,允许新请求进来测试服务是否恢复正常,若命令执行成功则关闭断路器,若失败进入下一个5s睡眠期

------------------

配置:https://www.cnblogs.com/zhangwanhua/p/7742703.html

原文地址:https://www.cnblogs.com/yfzhou528/p/13532097.html