hystrix三种降级策略,分别是:

  • 熔断触发降级
  • 超时触发降级
  • 资源隔离触发降级,又分了线程池与信号量两种

下面结合示例分别介绍下。

一,熔断触发降级

1,当某个服务失败率达到一定限度时将开启熔断器,这个服务后续再被调用时会被直接拒绝执行fallback逻辑(被调用方服务出现了问题,调用方进行熔断)
2,熔断器打开的两个条件

  1. 请求数达到设定的阀值
  2. 请求错误占比达到设定的阀值

3,示例

    /**
     * HystrixProperty的参数可参考 hystrixCommandProperties
     * 熔断触发降级
     * @return
     * 10s内(默认10s)当发起了超过5次请求,且失败率超过50%,熔断自动开启,
     * 从熔断开启到后续5s之内的请求,都不会进入到方法里,并
     * 且直接触发fallback这个回调方法返回。
     */
    @GetMapping("/circuitBreaker/{num}")
    @HystrixCommand(commandProperties  = {
            //开启熔断器功能
            @HystrixProperty (name = "circuitBreaker.enabled" ,value = "true"),
            //设置最小请求数
            @HystrixProperty(name = "circuitBreaker.requestVolumeThreshold",value ="5"),
            //熔断时间5秒
            @HystrixProperty(name = "circuitBreaker.sleepWindowInMilliseconds" , value ="5000"), 
            //错误流程比例
             @HystrixProperty(name="circuitBreaker.errorThresholdPercentage",value = "50") 

    } ,fallbackMethod = "fallback")
    public String circuitBreaker(@PathVariable("num")int num){
        if(num%2==0){
            return "正常访问";
        }

        throw new RuntimeException("");
    }
    //入参与请求方法入参需一致
    public String fallback(int num){
        return "熔断触发降级";
    }

打开熔断器开关

@SpringBootApplication
@EnableCircuitBreaker
public class App {
    public static void main(String[] args) {
        SpringApplication.run(App.class,args);
    }

}

这个示例当请求次数超过5次也就是第6次的时候,如果错误率超过了50%则会打开熔断器并进入fallback逻辑,且熔断器在打开的5s内都会执行ballback逻辑。

二,超时触发降级

1,当某个服务访问时间超过指定时间,可认为这个服务已经失败而不会继续等待,然后降级返回。

2,示例

    /**
     * 超时时间触发降级
     * @return
     */
    @GetMapping("/timeOut")
    @HystrixCommand(commandProperties  = {
        //启动超时触发降级
        @HystrixProperty(name = "execution.timeout.enabled" , value = "true"),
        //超过1s就触发降级
        @HystrixProperty(name = "execution.isolation.thread.timeoutInMilliseconds" , value = "1000"),
    } ,fallbackMethod = "fallback")
    public String timeOut() throws InterruptedException {
        Thread.sleep(3000) ;
        return "正常访问";

    }


    public String fallback(){
        return "触发降级";
    }

三,资源隔离触发降级

1,资源隔离触发降级分两种:线程池与信号量,hystrix默认使用的是线程池

先来看下信号量

信号量是限制请求并发数,如果超过了设定的值则触发降级。信号量的特点是使用容器(如tomcat)的线程处理请求,不涉及线程的上下切换,因为没有超时机制,所以适合不依赖外部服务的场景。

     public String fallback(){
        return "触发降级";
    }

    @GetMapping("/semaphore")
    @HystrixCommand(
            commandProperties = {
                    //隔离方式,有信号量与线程池两种
                    @HystrixProperty(name = "execution.isolation.strategy" , value = "SEMAPHORE"),
                    //信号量大小,默认为10,建议500-1000.
                    //这里表示这个服务同时不能超过2个并发请求
                    @HystrixProperty(name = "execution.isolation.semaphore.maxConcurrentRequests" , value = "2") 
            },
            fallbackMethod = "fallback"
    )
    public String semaphore() throws InterruptedException {
        return "semaphore正常访问";
    }

再来看下线程池的方式

hystrix将需要被隔离的资源或服务抽象成一个command对象,然后使用设定好的且独立的线程池执行,这样就不会影响到其它的服务。
线程池隔离的一个特点是在容器(如tomcat)线程之外创建了新的线程池,也就需要额外的维护这个线程池,这会有一定的开销(但官方的测试报告说开销并不大)。

 private int num1 = 1;
   
@HystrixCommand(
            commandProperties = {
                    //使用线程池的隔离
                    @HystrixProperty(name = "execution.isolation.strategy" , value = "THREAD"),  
                    //超时设置为3秒
                    @HystrixProperty(name = "execution.isolation.thread.timeoutInMilliseconds" , value = "3000"),  

            },
            threadPoolProperties = {
                    //线程池大小
                    @HystrixProperty(name = "coreSize" , value = "20"), 
                    //等待队列长度
                    @HystrixProperty(name = "maxQueueSize" , value = "1000"),     
                    //线程存活时间
                    @HystrixProperty(name = "keepAliveTimeMinutes", value = "2"),
                    /**
                     * 即使maxQueueSize没有达到,达到
                     * queueSizeRejectionThreshold该值后,
                     * 请求也会被拒绝。因为maxQueueSize不能被动态修改,
                     * 这个参数将允许我们动态设置该值
                     */
                    @HystrixProperty(name = "queueSizeRejectionThreshold" , value = "800"),  
            },
            groupKey = "ThreadService", commandKey = "thread" ,threadPoolKey = "ThreadService",
            fallbackMethod = "fallback"
            )
    public void  thread() throws  Exception  {
        Thread.sleep(1000);
        System.out.println(Thread.currentThread() + "正常访问" + num1++);
    }



    public void fallback(){
        System.out.println("熔断时间:" + new Date());
    }

需要注意下的是‘超时时间’timeoutInMilliseconds,示例中设置的是3s,使用的时候可能会在第4s的时候才熔断,这个和线程启动有关,时间上会略有出入。


步履不停
38 声望13 粉丝

好走的都是下坡路


« 上一篇
hystrix学习