Spring Cloud Hystrix熔断器隔离方案

Hystrix组件提供了两种隔离的解决方案:线程池隔离和信号量隔离。两种隔离方式都是限制对共享资源的并发访问量,线程在就绪状态、运行状态、阻塞状态、终止状态间转变时需要由操作系统调度,占用很大的性能消耗;而信号量是在访问共享资源时,进行tryAcquire,tryAcquire成功才允许访问共享资源。

线程池隔离

不同的业务线之间选择用线程池隔离,降低互相影响的概率。设置隔离策略为线程池隔离:

.withExecutionIsolationStrategy(HystrixCommandProperties.ExecutionIsolationStrategy.THREAD));在Hystrix内部,是根据properties.executionIsolationStrategy().get()这个字段判断隔离级别。如在getRunObservableDecoratedForMetricsAndErrorHandling这个方法中会先判断是不是线程池隔离,如果是就获取线程池,如果不是则进行信号量隔离的操作。

如果是线程池隔离,还需要设置线程池的相关参数如:线程池名字andThreadPoolKey , coreSize(核心线程池大小) , KeepAliveTimeMinutes(线程存存活时间),MaxQueueSize(最大队列长度),QueueSizeRejectionThreshold(拒绝执行的阀值)等等。

.andThreadPoolPropertiesDefaults(HystrixThreadPoolProperties.Setter().withCoreSize(resourcesManager.getThreadPoolProperties(platformProtocol.getAppId()).getCoreSize())
                                    .withKeepAliveTimeMinutes(resourcesManager.getThreadPoolProperties(platformProtocol.getAppId()).getKeepAliveSeconds())
                                    .withMaxQueueSize(resourcesManager.getThreadPoolProperties(platformProtocol.getAppId()).getMaxQueueSize())

                                    .withQueueSizeRejectionThreshold(resourcesManager.getThreadPoolProperties(platformProtocol.getAppId()).getQueueSizeRejectionThreshold()))

threadPoolKey 也是线程池的名字的前缀,默认前缀是 hystrix 。在Hystrix中,核心线程数和最大线程数是一致的,减少线程临时创建和销毁带来的性能开销。线程池的默认参数都在HystrixThreadPoolProperties中,重点讲解一下参数queueSizeRejectionThreshold 和maxQueueSize 。queueSizeRejectionThreshold默认值是5,允许在队列中的等待的任务数量。maxQueueSize默认值是-1,队列大小。如果是Fast Fail 应用,建议使用默认值。线程池饱满后直接拒绝后续的任务,不再进行等待。代码如下HystrixThreadPool类中:

@Override
        public boolean isQueueSpaceAvailable() {
            if (queueSize <= 0) {
                // we don‘t have a queue so we won‘t look for space but instead
                // let the thread-pool reject or not
                return true;
            } else {
                return threadPool.getQueue().size() < properties.queueSizeRejectionThreshold().get();
            }

        }

线程池一旦创建完成,相关参数就不会更改,存放在静态的ConcurrentHashMap中,key是对应的commandKey 。而queueSizeRejectionThreshold是每个命令都是设置的。

线程池的相关参数都保存在HystrixThreadPool这个类文件中,线程池的创建方法getThreadPool则在HystrixConcurrencyStrategy类文件中。从getThreadPool方法可以看出线程池的名字就是hystrix-threadPoolKey-threadNumber.

@Override
            public Thread newThread(Runnable r) {
                Thread thread = new Thread(r, "hystrix-" + threadPoolKey.name() + "-" + threadNumber.incrementAndGet());
                thread.setDaemon(true);
                return thread;

            }

     

在HystrixThreadPool实现类的构造方法中,并发HystrixConcurrencyStrategy实例是通过HystrixPlugins获取的,所以可以通过HystrixPlugins设置自定义插件。具体的HystrixPlugins如何使用,会在后面章节中讲解。

线程池的创建

     前面说了,在Hystrix内部大部分类都是单实例,同样ThreadPool也不例外,也是单实例。并且相同commandKey的依赖还必须是使用同一个线程池。这就需要把ThreadPool保存在一个静态的map中,key是commandKey,同时要保证线程安全,Hytstrix使用了ConcurrentHashMap。关于为什么不适用HashTable保证线程安全问题的疑问请自行Google。线程池的创建在HystrixThreadPool这个类文件中的内部类Factory中的getInstance方法。

/* package */final static ConcurrentHashMap<String, HystrixThreadPool> threadPools = new ConcurrentHashMap<String, HystrixThreadPool>();

     String key = threadPoolKey.name();


            // this should find it for all but the first time
            HystrixThreadPool previouslyCached = threadPools.get(key);
            if (previouslyCached != null) {
                return previouslyCached;
            }

// if we get here this is the first time so we need to initialize
            synchronized (HystrixThreadPool.class) {
                if (!threadPools.containsKey(key)) {
                    threadPools.put(key, new HystrixThreadPoolDefault(threadPoolKey, propertiesBuilder));
                }
            }

            return threadPools.get(key);

线程池的使用

HystrixCommand类的execute()内部调用了queue() ,queue又调用了父类AbstractCommand的toObservable方法,toObservable方法处理了是否可缓存问题后,交给了getRunObservableDecoratedForMetricsAndErrorHandling方法,这个方法设置了一系列的executionHook之后,交给了getExecutionObservableWithLifecycle,这个方法通过getExecutionObservable()获取了执行器。getExecutionObservable()是个抽象方法,具体实现放在了子类:HystrixCommand和HystrixObservableCommand类中。下面是HystrixCommand类中的getExecutionObservable方法实现:

final protected Observable<R> getExecutionObservable() {
        return Observable.create(new OnSubscribe<R>() {

@Override
            public void call(Subscriber<? super R> s) {
                try {
                    s.onNext(run());
                    s.onCompleted();
                } catch (Throwable e) {
                    s.onError(e);
                }
            }

});
    }

在这个Call方法中执行了具体的业务逻辑run() ;

转自

时间: 2024-10-21 03:08:44

Spring Cloud Hystrix熔断器隔离方案的相关文章

Spring Cloud Hystrix - 服务容错

服务容错和Hystrix 在微服务架构中,由于某个服务的不可用导致一系列的服务崩溃,被称之为雪崩效应.所以防御服务的雪崩效应是必不可少的,在Spring Cloud中防雪崩的利器就是Hystrix,Spring Cloud Hystri是基于Netflix Hystrix实现的.Hystrix的目标在于通过控制那些访问远程系统.服务和第三方库的节点,从而对延迟和故障提供更强大的容错能力.Hystrix 具备服务降级.服务容错.服务熔断.线程和信号隔离.请求缓存.请求合并以及服务监控等强大功能.

笔记:Spring Cloud Hystrix 服务容错保护

由于每个单元都在不同的进程中运行,依赖通过远程调用的方式执行,这样就有可能因为网络原因或是依赖服务自身问题出现调用故障或延迟,而这些问题会直接导致调用方的对外服务也出现延迟,若此时调用方的请求不断增加,最后就会因等待出现故障的依赖方响应形成任务积压,最终导致自身服务的瘫痪. 在微服务架构中,存在着大量的服务单元,若一个单元出现故障,就很容易因依赖关系而引发故障的蔓延,最终导致整个系统的瘫痪,这样的架构相较传统架构更加不稳定,为了解决这样的问题,产生了断路器等一系列的服务保护机制. 在分布式架构中

第五章 服务容错保护:Spring Cloud Hystrix

在微服务架构中,我们将系统拆分为很多个服务,各个服务之间通过注册与订阅的方式相互依赖,由于各个服务都是在各自的进程中运行,就有可能由于网络原因或者服务自身的问题导致调用故障或延迟,随着服务的积压,可能会导致服务崩溃.为了解决这一系列的问题,断路器等一系列服务保护机制出现了. 断路器本身是一种开关保护机制,用于在电路上保护线路过载,当线路中有电器发生短路时,断路器能够及时切断故障电路,防止发生过载.发热甚至起火等严重后果. 在分布式架构中,断路器模式的作用也是类似的. 针对上述问题,Spring

第五章 服务容错保护: Spring Cloud Hystrix

在微服务架构中, 存在着那么多的服务单元, 若一个单元出现故障, 就很容易因依赖关系而引发故障的蔓延,最终导致整个系统的瘫痪,这样的架构相较传统架构更加不稳定.为了解决这样的问题, 产生了断路器等一系列的服务保护机制 Spring Cloud Hystrix实现了断路器. 线程隔离等一系列服务保护功能.它也是基于Netflix的开源框架Hystrix实现的, 该框架的目标在于通过控制那些访问远程系统. 服务和第三方库的节点, 从而对延迟和故障提供更强大的容错能力.Hystrix具备服务降级. 服

微服务架构之spring cloud hystrix&amp;hystrix dashboard

在前面介绍spring cloud feign中我们已经使用过hystrix,只是没有介绍,spring cloud hystrix在spring cloud中起到保护微服务的作用,不会让发生的异常无边界的蔓延下去,很像我们电路中的保险设置,有超压或者线路有问题就即时的断开,保护用电设备不被损坏,这篇文章就来介绍spring cloud hystrix及其hystrix dashboard. (一) 版本说明 a) Spring boot 2.0.6.RELEASE b) Spring clou

SpringCloud---服务容错保护---Spring Cloud Hystrix

1.概述 1.1 在分布式架构中,存在着许多的服务单元,若一个单元出现故障,很容易因依赖关系引发故障的蔓延,最终导致整个系统的瘫痪: 为了解决这样的问题,产生了断路器等服务保护机制: 1.2 分布式架构中,当某个服务单元发生故障之后,通过断路器的故障监控,向调用方返回一个错误响应,而不是长时间等待,这样不会使得线程因调用故障服务被长时间占用不释放,避免了故障在分布式系统中的蔓延: 1.3 Spring Cloud Hystrix实现了断路器.线程隔离等一系列服务保护功能: 基于Netflix的开

Spring Cloud Hystrix理解与实践(一):搭建简单监控集群

前言 在分布式架构中,所谓的断路器模式是指当某个服务发生故障之后,通过断路器的故障监控,向调用方返回一个错误响应,这样就不会使得线程因调用故障服务被长时间占用不释放,避免故障的继续蔓延.Spring Cloud Hystrix实现了断路器,线程隔离等一系列服务保护功能,它是基于Netflix的开源框架Hystrix实现的. 目的不是介绍Hystrix的与原理.及其使用等(有时间也要记录啊),而是通过实战搭建一个简单的监控集群,使用Hystrix Dashboard仪表盘动态监控展示以此来加深对H

笔记:Spring Cloud Hystrix 异常处理、缓存和请求合并

异常处理 在 HystrixCommand 实现的run方法中抛出异常,除了 HystrixBadRequestException之外,其他异常均会被Hystrix 认为命令执行失败并触发服务降级处理逻辑,所以当需要在命令中执行抛出不触发降级的异常时使用他,在使用注解配置实现 Hystrix 命令时,支持忽略指定异常类型功能,只需要通过设置 @HystrixCommand 注册的 ignoreException 参数,示例代码如下: @HystrixCommand (ignoreExceptio

spring cloud: Hystrix(四):feign类似于hystrix的断容器功能

spring cloud: Hystrix(四):feign使用hystrix @FeignClient支持回退的概念:fallback方法,这里有点类似于:@HystrixCommand(fallbackMethod = "notfindback")的fallbackMethod 方法. fallback方法调用的是一个类.,feign也有:/health, /health.stream地址信息 http://192.168.1.4:7601/health 1.首先要在配置件开启hy