美文网首页
Hystrix实战之实现降级和熔断

Hystrix实战之实现降级和熔断

作者: 先生zeng | 来源:发表于2020-04-23 15:06 被阅读0次

    通过配置中心可以进行人工降级,而我们也需要根据服务的超时时间进行自动降级,下面主要介绍如何使用Hystrix进行降级,关于其他一些配置,可以看上一篇文章:
    基于Hystrix实现线程隔离技术-运用线程池

    1. 使用Hystrix进行降级

    如何使用可以看以下代码:

    
    public class HystrixProblemServiceCommand extends HystrixCommand<List<Problem>> {
    
        // 组名
        private static final String GROUP_KEY = "qa";
    
        // 命令标识名
        private static final String COMMAND_KEY = "query";
    
        // 线程池名
        private static final String THREADPOOL_KEY = "qa-pool";
    
        @Autowired
        private ProblemService problemService;
    
        public HystrixProblemServiceCommand() {
            super(setter());
        }
    
        private static Setter setter() {
    
            // 服务分组
            HystrixCommandGroupKey hystrixCommandGroupKey = HystrixCommandGroupKey.Factory.asKey(GROUP_KEY);
    
            // 服务唯一标识
            HystrixCommandKey commandKey = HystrixCommandKey.Factory.asKey(COMMAND_KEY);
    
            // 线程池名称
            HystrixThreadPoolKey threadPoolKey = HystrixThreadPoolKey.Factory.asKey(THREADPOOL_KEY);
    
            // 线程池配置
            HystrixThreadPoolProperties.Setter thresholdConfig = HystrixThreadPoolProperties.Setter()
                    .withCoreSize(10)   // 核心线程池大小
                    .withKeepAliveTimeMinutes(5)   //   空闲线程存活时间
                    .withMaxQueueSize(Integer.MAX_VALUE)        // 线程池队列大小
                    .withQueueSizeRejectionThreshold(1000); //限定当前队列大小
    
    
            // 命令属性配置,设置隔离策略为线程隔离
            HystrixCommandProperties.Setter isolationStrategy = HystrixCommandProperties.Setter()
                    // 设置隔离为线程隔离
                    .withExecutionIsolationStrategy(HystrixCommandProperties.ExecutionIsolationStrategy.THREAD)
                    // 设置启用降级处理
                    .withFallbackEnabled(true)
                    // 设置如果请求超过了并发信号量限制,则不再尝试调用getFallback方法,而是快速失败
                    .withFallbackIsolationSemaphoreMaxConcurrentRequests(100)
                    // 隔离策略为THREAD时,当执行线程执行超时时,是否进行中断处理,设置为true
                    .withExecutionIsolationThreadInterruptOnFutureCancel(true)
                    //当隔离策略为THREAD时,当执行线程执行超时时,是否进行中断处理,默认为true。
                    .withExecutionIsolationThreadInterruptOnTimeout(true)
                    //是否启用执行超时机制,默认为true。
                    .withExecutionTimeoutEnabled(true)
                    // 执行超时时间,默认为1000毫秒,如
                    .withExecutionTimeoutInMilliseconds(1000);
    
            /*return HystrixCommand.Setter.withGroupKey(HystrixCommandGroupKey.Factory.asKey(GROUP_KEY))
                    .andCommandKey(HystrixCommandKey.Factory.asKey(COMMAND_KEY))
                    .andThreadPoolKey(HystrixThreadPoolKey.Factory.asKey(THREADPOOL_KEY))
                    .andCommandPropertiesDefaults(HystrixCommandProperties.Setter().withExecutionIsolationStrategy(HystrixCommandProperties.ExecutionIsolationStrategy.THREAD));*/
            return HystrixCommand.Setter.withGroupKey(hystrixCommandGroupKey).andCommandKey(commandKey).andThreadPoolKey(threadPoolKey).andThreadPoolPropertiesDefaults(thresholdConfig).andCommandPropertiesDefaults(isolationStrategy);
        }
    
        @Override
        protected List<Problem> run() throws Exception {
    //可以抛出异常或者模拟超时
            return problemService.findAll();
        }
    
        @Override
        protected List<Problem> getFallback() {
            // 降级方法
            return new ArrayList<>();
        }
    
        public ProblemService getProblemService() {
            return problemService;
        }
    
        public void setProblemService(ProblemService problemService) {
            this.problemService = problemService;
        }
    }
    

    整体执行流程如下:



    首先,Command会调用run方法,如果run方法超时或者抛出异常,且启用了降级处理,则调用getFallback方法进行降级。

    而降级处理主要有两部分处理: HystrixCommandProperties配置和getFallback降级处理方法。

    HystrixCommandProperties配置:

    withFallbackEnabled: 是否启用降级处理,如果启用了,则在超时或异常时调用getFallback进行降级处理,默认为开启。

    withFallbacklsolationSemaphoreMaxConcurrentRequests: fall back方法的信号量配置,配置getFallback方法并发请求的信号量,如果请求超过了并发信号量限制,则不再尝试调用getFallback方法,而是快速失败,默认信号量为10。

    withExecutionlsolationThreadlnterruptOnFutureCancel : 隔离策略为THREAD时,当执行线程执行超时时,是否进行中断处理,即Future#cancel(true)处理,默认为false。

    withExecutionlsolationThreadlnterruptOnTimeout:当隔离策略为THREAD时,当执行线程执行超时时,是否进行中断处理,默认为true。跟上一条配置的区别在于执行是否有返回值。

    withExecutionTimeoutEnabled:是否启用执行超时机制,默认为true。

    withExecutionTimeoutlnMilliseconds:执行超时时间,默认为1000毫秒,如果命令是线程隔离,且配置了executionlsolationThreadlnterruptOnT1meout = true, 则执行线程将执行中断处理。

    当开启了降级处理,run方法超时或者异常时将会调用getFallback处理,使用getFallback时需要注意以下几点:

    • 其最大并发数受fallbackisolationSemaphoreMaxConcurrentRequests控制,因此,如果失败率非常高,则要重新配置该参数,如果最大并发数超了该配置,则不会再执行getFallback, 而是快速失败,抛出如"HystrixRuntimeException: GetStockServiceCommand fallback execution rejected"的异常。
    • 该方法不能进行网络调用(HTTP调用其他服务),应该只是使用缓存的数据,或者静态数据(如我们的问题方法返回获取失败)。
    • 如果必须走网络调用,则应该在getFallback方法中调用另 一 个Command实现,通过Command可以有降级和熔断机制保护应用,而getFallback只有fallbacklsolationSemaphoreMaxConcurrentRequests参数控制最大并发数。

    在处理业务代码时,可以使用以下方法,判断执行的状态:
    • isResponseTimedOut: 响应是否超时了。
    • isFailedExecution: 执行是否失败了,如抛出了异常。
    • getFailedExecutionException: 获取失败后的执行异常,即run方法抛出的异常。
    • isResponseFromFallback:是否是getFallback返回的响应。

    2.使用Hystrix实现熔断

    熔断这一概念来源于电子工程中的断路器(Circuit Breaker)。在互联网系统中,当下游服务因访问压力过大而响应变慢或失败,上游服务为了保护系统整体的可用性,可以暂时切断对下游服务的调用。

    这种牺牲局部,保全整体的措施就叫做熔断。

    对于熔断机制的实现,Hystrix设计了三种状态:

    1.熔断关闭状态(Closed)服务没有故障时,熔断器所处的状态,对调用方的调用不做任何限制。

    2.熔断开启状态(Open)在固定时间窗口内(Hystrix默认是10秒),接口调用出错比率达到一个阈值(Hystrix默认为50%),会进入熔断开启状态。进入熔断状态后,后续对该服务接口的调用不再经过网络,直接执行本地的fallback方法。

    3.半熔断状态(Half-Open)在进入熔断开启状态一段时间之后(Hystrix默认是5秒),熔断器会进入半熔断状态。所谓半熔断就是尝试恢复服务调用,允许有限的流量调用该服务,并监控调用成功率。如果成功率达到预期,则说明服务已恢复,进入熔断关闭状态;如果成功率仍旧很低,则重新进入熔断关闭状态。

    Hystrix提供了熔断实现,熔断后会自动降级处理,如下图所示:


    image.png

    如何配置?

    // 命令属性配置,设置隔离策略为线程隔离
    HystrixCommandProperties.Setter isolationStrategy = HystrixCommandProperties.Setter()
    // 设置隔离为线程隔离
     .withExecutionIsolationStrategy(HystrixCommandProperties.ExecutionIsolationStrategy.THREAD)
    // 设置启用降级处理
      .withFallbackEnabled(true)
    // 设置如果请求超过了并发信号量限制,则不再尝试调用getFallback方法,而是快速失败
    .withFallbackIsolationSemaphoreMaxConcurrentRequests(100)
    // 隔离策略为THREAD时,当执行线程执行超时时,是否进行中断处理,设置为true
    .withExecutionIsolationThreadInterruptOnFutureCancel(true)
    //当隔离策略为THREAD时,当执行线程执行超时时,是否进行中断处理,默认为true。
    .withExecutionIsolationThreadInterruptOnTimeout(true)
    //是否启用执行超时机制,默认为true。
    .withExecutionTimeoutEnabled(true)
    // 执行超时时间,默认为1000毫秒,如
    .withExecutionTimeoutInMilliseconds(1000)
    // 是否开启熔断机制
    .withCircuitBreakerEnabled(true)
    // 是否强制关闭熔断开关
    .withCircuitBreakerForceClosed(false)
    // 是否强制打开熔断开关
    .withCircuitBreakerForceOpen(false)
    // 一 个采样时间窗口内,失败率超过该配置,则自动打开熔断开关实现降级处理,
    // 即快速失败。默认配置下采样周期为10s, 失败率为50% 。
    .withCircuitBreakerErrorThresholdPercentage(50)
    // 开关闭合的情况下,在进行失败率判断之前,一个采样周期内必须进行至少N个请求才能进行采样统计,
    // 目的是有足够的采样使得失败率计算正确,默认为20 。
    .withCircuitBreakerRequestVolumeThreshold(20)
    // 熔断后的重试时间窗口,且在该时间窗口内只允许一 次重试。
    //如果重试成功,则将重置H ealth采样统计并闭合熔断开关实现快速恢复
    //否则熔断开关还是打开状态,执行快速失败。
    .withCircuitBreakerSleepWindowInMilliseconds(5000);
    

    熔断后将降级调用getFallback 进行处理.会通过commond的如下方法判断:

    HystrixProblemServiceCommand hystrixProblemServiceCommand = new HystrixProblemServiceCommand();
    hystrixProblemServiceCommand.setProblemService(problemService);
    // 熔断开关是否打开 
    hystrixProblemServiceCommand.isCircuitBreakerOpen();  
    hystrixProblemServiceCommand.isResponseShortCircuited();
    

    待续。。。

    相关文章

      网友评论

          本文标题:Hystrix实战之实现降级和熔断

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