Hystrix使用详解

1.服务降级

当HystrixCommand在调用期间发生异常时会导致服务降级,此时会转入指定的fallback方法中执行降级逻辑

    @HystrixCommand(fallbackMethod = "fallback",ignoreExceptions = NullPointerException.class)
    public User findUser(Integer id){
        return restTemplate.getForObject("http://hello-service/user/{1}",User.class,id);
    }
    //注意降级策略的返回值必须与可能触发降级策略的调用相同
    public User fallback(Integer id,Throwable t){//使用参数t获取造成服务降级的异常
        log.info(t.getMessage());
        User defaultUser = new User(3,"xjf");
        return defaultUser;
    }

可以指定注解中的ignoreExceptions属性指定异常直接抛出而不是执行降级逻辑,需要注意降级方法必须与原方法保持相同的返回值


2.命令名称,分组与线程划分

Hystrix默认使用@HystrixCommand注解的方法名作为命令名称,可以对命令进行分组,默认同一组的命令使用相同的线程池。若存在业务上属于同组但执行环境需要隔离的情况,则可以指定线程划分。

    @HystrixCommand(fallbackMethod = "fallback",ignoreExceptions = NullPointerException.class,
    commandKey = "findUser",groupKey = "userGroup",threadPoolKey = "***")

3.开启缓存

Hystrix也可以缓存对同一服务的请求结果以减轻服务的负载压力,但需要注意这个缓存仅在同一个用户的请求上下文中有效。

开启HystrixContext
1.在主方法上加入注解@ServletComponentScan
2.创建HystrixRequestContextServletFilter

package com.cfh.eurekaconsumer.filter;

import com.netflix.hystrix.strategy.concurrency.HystrixRequestContext;

import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import java.io.IOException;

@WebFilter(filterName = "hystrixRequestContextServletFilter",urlPatterns = "/*",asyncSupported = true)
public class HystrixRequestContextServletFilter implements Filter {
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
        //初始化Hystrix请求上下文
        HystrixRequestContext context = HystrixRequestContext.initializeContext();
        try {
            //请求正常通过
            chain.doFilter(request, response);
        } finally {
            //关闭Hystrix请求上下文
            context.shutdown();
        }
    }

    @Override
    public void init(FilterConfig filterConfig) throws ServletException {

    }

    @Override
    public void destroy() {

    }
}

使用@CacheResult注解开启缓存,指定cacheKeyMethod为缓存key值的生成策略。若不指定则默认使用HystrixCommand的所有参数的组合作为缓存的key

    //使用ignoreExceptions可以让指定的异常不触发降级策略而是直接抛出
    //使用commandKey与groupkey参数指定命令名与命令组名(默认同组的命令使用同一个线程池)
    @HystrixCommand(fallbackMethod = "fallback",ignoreExceptions = NullPointerException.class,
    commandKey = "findUser",groupKey = "userGroup")
    @CacheResult(cacheKeyMethod = "getCacheKey")//开启缓存
    public User findUser(Integer id){//指定缓存的key
        return restTemplate.getForObject("http://hello-service/user/{1}",User.class,id);
    }

指定id的值为缓存的key

    public String getCacheKey(Integer id){
        return String.valueOf(id);
    }

当调用可能导致缓存失效的命令时需要使用@CacheRemove注解清空缓存,同时必须要指定生成相应缓存的CommandKey

    @HystrixCommand
    @CacheRemove(commandKey = "findUser")//由于更新user会导致缓存失效所以需要使用@CacheRemove注解清缓存
    public void updateUser(Integer id){
        log.info("清空失效缓存");
        User updateUser = new User(id,"newName");
        restTemplate.postForEntity("http://hello-service/user/update/{1}",updateUser,void.class,id);
    }

4.聚合请求
hystrix提供了在一个请求窗口内对同一个服务的聚合请求的功能(需要服务放提供对聚合请求处理的服务),以减轻因为通信次数的增加导致的线程消耗与通信资源消耗。

通过@HystrixCollapser注解开启请求合并功能,并指定合并方法(合并方法必须是HystrixCommand)以及相关属性(如这里指定了一个请求窗口的大小)。

    //开启请求合并器,设置合并窗口时间为100ms
    @HystrixCollapser(batchMethod = "findAll",collapserProperties = {@HystrixProperty(name ="timerDelayInMilliseconds",value = "100")})
    public User findUser2(Integer id){//指定缓存的key
        return null;
    }

聚合之后的请求

    @HystrixCommand
    //聚合之后的请求
    public List<User> findAll(List<Integer> ids){
        log.info(Thread.currentThread().getName());
        ParameterizedTypeReference<List<User>> responseType = new ParameterizedTypeReference<List<User>>() {
        };
        //服务方提供了处理聚合请求的能力
        return restTemplate.exchange("http://hello-service/users?ids={1}",HttpMethod.GET,
                null,responseType,StringUtils.join(ids,",")).getBody();
    }

Hystrix会将聚合请求的结果分用到各个单独请求的结果上,调用者的感知就好像调用了一个独立的方法。

因为聚合本身会带来一定的开销,因此建议只对高并发与高延迟的服务开启请求聚合功能


相关代码请参考:
https://github.com/Tinysakura/studyhistrix/commits/master

你可能感兴趣的:(spring,cloud)