zoukankan      html  css  js  c++  java
  • Hystrix缓存、熔断、隔离、降级

    一、引言

      上篇,我们已经讲到了进入HystrixCommand的queue方法,方法中最关键的就是toObservable方法,利用RxJava的事件发布订阅机制,实现hystrix的功能。

    二、缓存

      缓存,是HystrixCommand进入toObservable方法的第一个主流程,先读缓存,如果缓存命中则直接返回;否则继续执行,待执行结束后将结果放入缓存。

        protected final HystrixRequestCache requestCache;
        protected AbstractCommand(···) {
            ···
            //构建缓存单例
            this.requestCache = HystrixRequestCache.getInstance(this.commandKey, this.concurrencyStrategy);
        }
            //订阅时才生效的操作符
            return Observable.defer(new Func0<Observable<R>>() {
                @Override
                public Observable<R> call() {
                     // 设置命令状态
                    if (!commandState.compareAndSet(CommandState.NOT_STARTED, CommandState.OBSERVABLE_CHAIN_CREATED)) {
                        IllegalStateException ex = new IllegalStateException("This instance can only be executed once. 
                                        Please instantiate a new instance.");
                        //
                        throw new HystrixRuntimeException(FailureType.BAD_REQUEST_EXCEPTION, _cmd.getClass(),
                     getLogMessagePrefix() + " command executed multiple times - this is not permitted.", ex, null);
                    }
                    //命令执行开始时间
                    commandStartTimestamp = System.currentTimeMillis();
                    //是否开启请求日志
                    if (properties.requestLogEnabled().get()) {
                        // 记录执行的命令
                        if (currentRequestLog != null) {
                            currentRequestLog.addExecutedCommand(_cmd);
                        }
                    }
                    //判断是否开启缓存 一般不会使用缓存 根据配置和getCacheKey来判断的
                    final boolean requestCacheEnabled = isRequestCachingEnabled();
                    //获取cacheKey HystrixCommand没有重写父类的这个方法,所以这里一直返回的是null
                    final String cacheKey = getCacheKey();
    
                    //缓存开启,先从缓存中获取
                    if (requestCacheEnabled) {
                        //从缓存获取HystrixCommandResponseFromCache
                        HystrixCommandResponseFromCache<R> fromCache = (HystrixCommandResponseFromCache<R>) requestCache.get(cacheKey);
                        if (fromCache != null) {
                            isResponseFromCache = true;
                            //返回Observable
                            return handleRequestCacheHitAndEmitValues(fromCache, _cmd);
                        }
                    }
                    //缓存中没有,或者没有开启
                    Observable<R> hystrixObservable =
                            //延迟生效的事件
                            Observable.defer(applyHystrixSemantics)
                                    .map(wrapWithAllOnNextHooks);
    
                    Observable<R> afterCache;
    
                    // 如果已经开启缓存 但是缓存未命中
                    if (requestCacheEnabled && cacheKey != null) {
                        // 封装命令HystrixCachedObservable
                        HystrixCachedObservable<R> toCache = HystrixCachedObservable.from(hystrixObservable, _cmd);
                        // 放入缓存中
                        HystrixCommandResponseFromCache<R> fromCache = 
                          (HystrixCommandResponseFromCache<R>) requestCache.putIfAbsent(cacheKey, toCache);
                        if (fromCache != null) {
                            toCache.unsubscribe();
                            isResponseFromCache = true;
                            return handleRequestCacheHitAndEmitValues(fromCache, _cmd);
                        } else {
                            afterCache = toCache.toObservable();
                        }
                    } else {
                        //没有开启缓存
                        afterCache = hystrixObservable;
                    }
    
                    return afterCache
                            //执行被终止时触发的监听,无论是正常终止还是异常终止
                            .doOnTerminate(terminateCommandCleanup)    
                            //订阅取消时触发的监听
                            .doOnUnsubscribe(unsubscribeCommandCleanup)
                            //执行完成时触发的监听
                            .doOnCompleted(fireOnCompletedHook);
                }
            });

    三、断路器

    配置

    circuitBreaker.enabled:是否允许使用断路器,默认true。
    circuitBreaker.forceOpen:是否强制开启断路器,默认false。
    circuitBreaker.forceClosed:是否强制关闭断路器,默认false。
    circuitBreaker.requestVolumeThreshold:滑动窗口时间内(默认metrics.rollingStats.timeInMilliseconds=10s),请求数量总数,达到n后才可以统计失败率进而执行熔断,默认20。
    circuitBreaker.errorThresholdPercentage:滑动窗口时间内(默认metrics.rollingStats.timeInMilliseconds=10s),错误率达到n%后,开启断路器,默认50。
    circuitBreaker.sleepWindowInMilliseconds:断路器开启后n毫秒内,拒绝请求,超过这个时间就可以尝试再次发起请求。

    断路器的实现也是在toObservable方法,第一步是缓存,第二步就是断路器,先看看他的初始化。

        protected final HystrixCircuitBreaker circuitBreaker;
        protected AbstractCommand(···) {
            //初始化断路器
            this.circuitBreaker = initCircuitBreaker(this.properties.circuitBreakerEnabled().get(), 
                circuitBreaker, this.commandGroup, this.commandKey, this.properties, this.metrics);        
        }
        
        private static HystrixCircuitBreaker initCircuitBreaker(boolean enabled, HystrixCircuitBreaker fromConstructor,
                                                                HystrixCommandGroupKey groupKey, HystrixCommandKey commandKey,
                                                                HystrixCommandProperties properties, HystrixCommandMetrics metrics) {
            // circuitBreaker.enabled = true
            if (enabled) { 
                if (fromConstructor == null) {
                    // 创建HystrixCircuitBreakerImpl
                    // 基于commandKey维度
                    return HystrixCircuitBreaker.Factory.getInstance(commandKey, groupKey, properties, metrics);
                } else {
                    return fromConstructor;
                }
            } else {
                // NoOpCircuitBreaker
                // allowRequest返回true
                // isOpen返回false
                return new NoOpCircuitBreaker();
            }
        }
        
        static class HystrixCircuitBreakerImpl implements HystrixCircuitBreaker {
            // 配置文件
            private final HystrixCommandProperties properties;
            // HystrixCommandMetrics负责HystrixCommand的指标统计管理
            private final HystrixCommandMetrics metrics;
            // 断路器开关
            private AtomicBoolean circuitOpen = new AtomicBoolean(false);
            // 首次打开时间 or 半开状态:上次尝试时间
            private AtomicLong circuitOpenedOrLastTestedTime = new AtomicLong();
            protected HystrixCircuitBreakerImpl(HystrixCommandKey key, HystrixCommandGroupKey commandGroup, 
                    HystrixCommandProperties properties, HystrixCommandMetrics metrics) {
                this.properties = properties;
                this.metrics = metrics;
            }
        }

    toObservable中定义了一个事件,会在后面被订阅消费

            final Func0<Observable<R>> applyHystrixSemantics = new Func0<Observable<R>>() {
                @Override
                public Observable<R> call() {
                    if (commandState.get().equals(CommandState.UNSUBSCRIBED)) {
                //当前状态为取消订阅,不发送任何事件
    return Observable.never(); } //主要请求流程,包括熔断、降级、隔离等处理 return applyHystrixSemantics(_cmd); } };
        private Observable<R> applyHystrixSemantics(final AbstractCommand<R> _cmd) {
            //标记开始执行,如果这个钩子抛出异常,那么会发生快速失败,不会走回退方法
            executionHook.onStart(_cmd);
    
            //如果断路器允许请求,执行后续逻辑
            if (circuitBreaker.allowRequest()) {
                ···
            } else {
                // 否则抛出断路器打开的异常,执行降级逻辑
                return handleShortCircuitViaFallback();
            }
        }
            //HystrixCircuitBreakerImpl
            public boolean allowRequest() {
                // 如果circuitBreaker.forceOpen=true,返回不能执行
                if (properties.circuitBreakerForceOpen().get()) {
                    // 配置了强制打开断路器
                    return false;
                }
                // 如果circuitBreaker.forceClosed=true,返回可以执行
                if (properties.circuitBreakerForceClosed().get()) {
                    // 调用isOpen,根据统计信息,更新断路器的开闭状态
                    isOpen();
                    // 这里不管siOpen的结果,直接允许所有请求通过
                    return true;
                }
                // 没特殊配置的情况下
                // 断路器关闭 或 半开状态允许尝试发起一次请求
                return !isOpen() || allowSingleTest();
            }

    是否打开

            public boolean isOpen() {
                // 如果断路器开启,直接返回开启
                if (circuitOpen.get()) {
                    return true;
                }
                // 获取滑动窗口内请求数量包装类对象
                HealthCounts health = metrics.getHealthCounts();
    
                // 检查是否超过了统计窗口容量
                if (health.getTotalRequests() < properties.circuitBreakerRequestVolumeThreshold().get()) {
                    // 总请求数没有达到阈值,直接返回false,关闭状态
                    return false;
                }
                //错误率小于阈值返回关闭
                if (health.getErrorPercentage() < properties.circuitBreakerErrorThresholdPercentage().get()) {
                    return false;
                } else {
                    // 错误率超出了阈值,尝试打开断路器
                    if (circuitOpen.compareAndSet(false, true)) {
                        // 这里设置当前时间为上一次断路器open的时间
                        circuitOpenedOrLastTestedTime.set(System.currentTimeMillis());
                        // 返回断路器已开启
                        return true;
                    } else {
                        // 这里用到cas,如果失败说明有其他线程想把断路器打开,
                        // 那么,竞争失败的线程直接返回断路器已打开就行了
                        return true;
                    }
                }
            }

    是否允许尝试发送一次请求

            public boolean allowSingleTest() {
                // 获取断路器上次开启的时间
                long timeCircuitOpenedOrWasLastTested = circuitOpenedOrLastTestedTime.get();
                // 1) 如果断路器是开启的
                // 2) 并且 当前时间 > 断路器上次开启的时间 + 配置circuitBreaker.sleepWindowInMilliseconds
                if (circuitOpen.get() && System.currentTimeMillis() > 
                  timeCircuitOpenedOrWasLastTested + properties.circuitBreakerSleepWindowInMilliseconds().get()) { // cas尝试修改上次断路器开启的时间 为 当前时间 if (circuitOpenedOrLastTestedTime.compareAndSet(timeCircuitOpenedOrWasLastTested, System.currentTimeMillis())) { //尝试放行一个请求 return true; } } //走到这,说明 //1、还没过hystrix的保护窗口期,直接返回false //2、cas竞争失败,因为只允许一次请求通过,所以此处让竞争成功的线程去发送请求 return false; }

    断路器打开,执行降级逻辑

        private Observable<R> handleShortCircuitViaFallback() {
            // 记录事件  断路器打开 执行fallback逻辑
            eventNotifier.markEvent(HystrixEventType.SHORT_CIRCUITED, commandKey);
            // 封装一个断路器已打开的异常
            Exception shortCircuitException = new RuntimeException("Hystrix circuit short-circuited and is OPEN");
            executionResult = executionResult.setExecutionException(shortCircuitException);
            try {
                //执行fallback逻辑
                return getFallbackOrThrowException(this, HystrixEventType.SHORT_CIRCUITED, FailureType.SHORTCIRCUIT,
                        "short-circuited", shortCircuitException);
            } catch (Exception e) {
                return Observable.error(e);
            }
        }

    四、资源隔离

    隔离策略

    execution.isolation.strategy:隔离策略,可选Thread、Semaphore,默认Thread。官方推荐,当有网络调用时,使用Thread;当纯内存操作或并发非常高导致创建线程资源消耗非常大时,使用Semaphore信号量。
    execution.timeout.enabled:HystrixCommand.run()是否有超时控制,默认true。
    execution.isolation.thread.timeoutInMilliseconds:超时时间,默认1s。不要被配置命名误导,目前无论是信号量隔离还是线程隔离策略,都可以通过这个属性设置超时时间。

    线程池配置

    coreSize:核心线程数,默认10。
    allowMaximumSizeToDivergeFromCoreSize:是否支持最大线程数配置,默认false,核心线程数等于最大线程数。
    maximumSize:最大线程数,默认10。
    maxQueueSize:线程池等待队列长度,默认-1,队列实现为SynchronousQueue。设置为大于0的数,队列实现为LinkedBlockingQueue。不支持动态更新这个配置,如果要更新这个配置需要重新初始化线程池。
    queueSizeRejectionThreshold:当maxQueueSize>0,因为maxQueueSize不支持动态更新,这个配置的目的是动态更新,来拒绝请求,默认5。
    keepAliveTimeMinutes:非核心线程空闲时间,默认1min。

    信号量配置

    execution.isolation.semaphore.maxConcurrentRequests:HystrixCommand.run同时执行的最大数量,默认10。

    1、信号量隔离

    toObservable方法的第三步就是资源隔离的实现,当然要断路器关闭或者允许一次请求通过的前提下circuitBreaker.allowRequest()为true,

            if (circuitBreaker.allowRequest()) {
                //获取信号量包装对象
                final TryableSemaphore executionSemaphore = getExecutionSemaphore();
                // 信号量是否被释放的标记
                final AtomicBoolean semaphoreHasBeenReleased = new AtomicBoolean(false);
                // 发布一个用于释放信号量的事件
                final Action0 singleSemaphoreRelease = new Action0() {
                    @Override
                    public void call() {
                        //尝试修改标记的值
                        if (semaphoreHasBeenReleased.compareAndSet(false, true)) {
                            // 如果修改成功,没有其他线程竞争或者和其他线程竞争成功 
                            // 信号量 -1
                            executionSemaphore.release();
                        }
                    }
                };
                // 异常标记事件
                final Action1<Throwable> markExceptionThrown = new Action1<Throwable>() {
                    @Override
                    public void call(Throwable t) {
                        eventNotifier.markEvent(HystrixEventType.EXCEPTION_THROWN, commandKey);
                    }
                };
                
                // 尝试获取信号量 
                // 策略是线程隔离的话 返回的对象是TryableSemaphoreNoOp 直接是true
                // 策略是信号量隔离的话 返回的对象是TryableSemaphoreActual 要进行逻辑判断
                if (executionSemaphore.tryAcquire()) {
                    try {
                        // 标记 开始 处理时间
                        executionResult = executionResult.setInvocationStartTime(System.currentTimeMillis());
                        // 执行后续流程
                        return executeCommandAndObserve(_cmd)
                                //发生错误时触发的事件
                                .doOnError(markExceptionThrown)
                                //执行终止时触发的事件
                                .doOnTerminate(singleSemaphoreRelease)
                                //取消订阅时触发的事件
                                .doOnUnsubscribe(singleSemaphoreRelease);
                    } catch (RuntimeException e) {
                        return Observable.error(e);
                    }
                } else {
                    // 超出信号量阈值 执行fallback逻辑
                    return handleSemaphoreRejectionViaFallback();
                }
            }

    获取信号量对象

        // 信号量对象
        protected final TryableSemaphore executionSemaphoreOverride;
            protected AbstractCommand(···,
                //子类在创建的时候 传值都是null 所以属性默认值一般为null
                TryableSemaphore executionSemaphore) {
            ···
            this.executionSemaphoreOverride = executionSemaphore;
        }
        
        // 静态成员变量 executionSemaphorePerCircuit 
        // 保存 commandKey 和 信号量 的 映射关系
        protected static final ConcurrentHashMap<String, TryableSemaphore> executionSemaphorePerCircuit 
                        = new ConcurrentHashMap<String, TryableSemaphore>(); //获取信号量 protected TryableSemaphore getExecutionSemaphore() { //判读隔离策略是否为 信号量 if (properties.executionIsolationStrategy().get() == ExecutionIsolationStrategy.SEMAPHORE) { // 如果策略是信号量 executionSemaphoreOverride在构造器中初始化的 一般为null if (executionSemaphoreOverride == null) { // 先从静态成员变量executionSemaphorePerCircuit获取信号量 TryableSemaphore _s = executionSemaphorePerCircuit.get(commandKey.name()); if (_s == null) { // 如果没有 创建Hystrix自己的信号量实现类TryableSemaphoreActual 放入map中 // putIfAbsent 如果存在不会进行替换 这里防止并发创建放入 executionSemaphorePerCircuit.putIfAbsent(commandKey.name(),
                      new TryableSemaphoreActual(properties.executionIsolationSemaphoreMaxConcurrentRequests())); // 从map中取出返回 TryableSemaphoreActual return executionSemaphorePerCircuit.get(commandKey.name()); } else { // 存在 直接返回 return _s; } } else { // 不为null 直接返回 return executionSemaphoreOverride; } } else { // 不是信号量 直接返回TryableSemaphoreNoOp return TryableSemaphoreNoOp.DEFAULT; } }

    尝试获取信号量

    信号量隔离实现

        static class TryableSemaphoreActual implements TryableSemaphore {
            
            protected final HystrixProperty<Integer> numberOfPermits;
            //信号量统计
            private final AtomicInteger count = new AtomicInteger(0);
    
            public TryableSemaphoreActual(HystrixProperty<Integer> numberOfPermits) {
                this.numberOfPermits = numberOfPermits;
            }
    
            @Override
            public boolean tryAcquire() {
                //信号量自增
                int currentCount = count.incrementAndGet();
                //判断当前信号量 是否大于 配置的信号量阈值
                if (currentCount > numberOfPermits.get()) {
                    // 大于 先自减 再返回false
                    count.decrementAndGet();
                    return false;
                } else {
                    // 小于 直接返回true
                    return true;
                }
            }
    
            @Override
            public void release() {
                // 信号量自减
                count.decrementAndGet();
            }
    
            @Override
            public int getNumberOfPermitsUsed() {
                // 获取当前信号量
                return count.get();
            }
    
        }

    线程池隔离实现

        //非信号量隔离 的默认实现
        static class TryableSemaphoreNoOp implements TryableSemaphore {
            public static final TryableSemaphore DEFAULT = new TryableSemaphoreNoOp();
            @Override
            public boolean tryAcquire() {
                return true;
            }
            @Override
            public void release() {}
            @Override
            public int getNumberOfPermitsUsed() {
                return 0;
            }
        }

    2、线程池隔离

      线程池隔离是在判断完信号量隔离之后的executeCommandAndObserve方法中,这个方法也是发起任务调度(发送请求)的核心方法。

    初始化线程池

    protected final HystrixThreadPool threadPool;
    //构造方法
    protected AbstractCommand(···,
                HystrixThreadPoolKey threadPoolKey,
                HystrixThreadPool threadPool,
                HystrixThreadPoolProperties.Setter threadPoolPropertiesDefaults) {
            // 获取HystrixThreadPoolKey,优先取传入的HystrixThreadPoolKey
            // 如果没传入取HystrixCommandGroupKey 如果跟feign结合使用的就是@feign的value属性
            this.threadPoolKey = initThreadPoolKey(threadPoolKey, this.commandGroup,
                       this.properties.executionIsolationThreadPoolKeyOverride().get()); // 构造时初始化threadPoolKey对应的HystrixThreadPool // 根据配置构造HystrixThreadPoolDefault this.threadPool = initThreadPool(threadPool, this.threadPoolKey,threadPoolPropertiesDefaults); } //初始化线程池 private static HystrixThreadPool initThreadPool(HystrixThreadPool fromConstructor, HystrixThreadPoolKey threadPoolKey, HystrixThreadPoolProperties.Setter threadPoolPropertiesDefaults) { if (fromConstructor == null) { return HystrixThreadPool.Factory.getInstance(threadPoolKey, threadPoolPropertiesDefaults); } else { return fromConstructor; } }

    执行后续请求

        private Observable<R> executeCommandAndObserve(final AbstractCommand<R> _cmd) {
            // 获取当前线程HystrixRequestContext ThreadLocal实现
            final HystrixRequestContext currentRequestContext = HystrixRequestContext.getContextForCurrentThread();
    
            // 定义一个onNext执行
            final Action1<R> markEmits = ···;
    
            // 定义一个完成事件
            final Action0 markOnCompleted = new Action0() {
                @Override
                public void call() {
                    if (!commandIsScalar()) {
                        long latency = System.currentTimeMillis() - executionResult.getStartTimestamp();
                        eventNotifier.markCommandExecution(getCommandKey(), properties.executionIsolationStrategy().get(),
                             (
    int) latency, executionResult.getOrderedList()); eventNotifier.markEvent(HystrixEventType.SUCCESS, commandKey); // 执行成功结果记录 executionResult = executionResult.addEvent((int) latency, HystrixEventType.SUCCESS); // 断路器标记成功 circuitBreaker.markSuccess(); } } }; // 降级处理 final Func1<Throwable, Observable<R>> handleFallback = ···; // 设置当前线程请求上下文 final Action1<Notification<? super R>> setRequestContext = new Action1<Notification<? super R>>() { @Override public void call(Notification<? super R> rNotification) { setRequestContextIfNeeded(currentRequestContext); } }; // 创建被观察者 Observable<R> execution; // 判断是否有超时配置 if (properties.executionTimeoutEnabled().get()) { // 如果execution.timeout.enabled=true // 执行后续逻辑 execution = executeCommandWithSpecifiedIsolation(_cmd) // HystrixObservableTimeoutOperator超时逻辑 .lift(new HystrixObservableTimeoutOperator<R>(_cmd)); } else { //没有超时配置 execution = executeCommandWithSpecifiedIsolation(_cmd); } // 订阅事件 return execution.doOnNext(markEmits)
              //完成时触发 .doOnCompleted(markOnCompleted) //发生错误时重新生成一个被观察者 触发onNext
              .onErrorResumeNext(handleFallback)
              // 每次发布新事件都会调用一次 .doOnEach(setRequestContext); }

    1)执行后续逻辑executeCommandWithSpecifiedIsolation(_cmd)

        private Observable<R> executeCommandWithSpecifiedIsolation(final AbstractCommand<R> _cmd) {
            // 判断隔离策略是否为 线程池
            if (properties.executionIsolationStrategy().get() == ExecutionIsolationStrategy.THREAD) {
                // 延迟生效的事件   标记我们正在线程中执行
                return Observable.defer(new Func0<Observable<R>>() {
                    @Override
                    public Observable<R> call() {
                // 封装执行结果 executionResult
    = executionResult.setExecutionOccurred(); // cas修改命令状态 创建修改为执行 if (!commandState.compareAndSet(CommandState.OBSERVABLE_CHAIN_CREATED, CommandState.USER_CODE_EXECUTED)) { return Observable.error(
                      new IllegalStateException("execution attempted while in state : " + commandState.get().name())); } // 标记开始 metrics.markCommandStart(commandKey, threadPoolKey, ExecutionIsolationStrategy.THREAD); // 如果超时 if (isCommandTimedOut.get() == TimedOutStatus.TIMED_OUT) { //发布 异常事件 return Observable.error(new RuntimeException("timed out before executing run()")); } // cas修改线程状态 就绪改为开始执行 if (threadState.compareAndSet(ThreadState.NOT_USING_THREAD, ThreadState.STARTED)) { // 线程数自增 HystrixCounters.incrementGlobalConcurrentThreads();
                   //标记线程已执行 threadPool.markThreadExecution();
    // 存储正在运行的命令 endCurrentThreadExecutingCommand = Hystrix.startCurrentThreadExecutingCommand(getCommandKey()); executionResult = executionResult.setExecutedInThread(); // try {
                     //暂时是一些空实现 executionHook.onThreadStart(_cmd); executionHook.onRunStart(_cmd); executionHook.onExecutionStart(_cmd);
    // 执行HystrixCommand.run方法 return getUserExecutionObservable(_cmd); } catch (Throwable ex) { return Observable.error(ex); } } else { // 发布 异常事件 return Observable.error(new RuntimeException("unsubscribed before executing run()")); } } })//执行终止时触发,修改当前线程状态为终止
            .doOnTerminate(···
    )
            //取消订阅时触发,修改线程状态为 取消订阅
            .doOnUnsubscribe(
    ···)
            //订阅事件 使用线程池线程调度的地方
            .subscribeOn(
    // getScheduler获取hystrix自定义的Scheduler threadPool.getScheduler(new Func0<Boolean>() { // 判断执行超时后,是否中断执行线程 @Override public Boolean call() { return properties.executionIsolationThreadInterruptOnTimeout().get() &&
                                   _cmd.isCommandTimedOut.get() == TimedOutStatus.TIMED_OUT; } }) ); } else { // 不是线程池隔离策略 不需要发布线程相关的事件 return Observable.defer(new Func0<Observable<R>>() { @Override public Observable<R> call() {
                //设置执行结果 executionResult
    = executionResult.setExecutionOccurred();
                //修改执行状态
    if (!commandState.compareAndSet(CommandState.OBSERVABLE_CHAIN_CREATED, CommandState.USER_CODE_EXECUTED)) { return Observable.error(
                       new IllegalStateException("execution attempted while in state : " + commandState.get().name())); }             //标记命令已执行 metrics.markCommandStart(commandKey, threadPoolKey, ExecutionIsolationStrategy.SEMAPHORE); // 存储正在运行的命令 endCurrentThreadExecutingCommand = Hystrix.startCurrentThreadExecutingCommand(getCommandKey()); try { executionHook.onRunStart(_cmd); executionHook.onExecutionStart(_cmd); // 执行HystrixCommand.run方法 return getUserExecutionObservable(_cmd); } catch (Throwable ex) { //If the above hooks throw, then use that as the result of the run method return Observable.error(ex); } } }); } }

    通过订阅事件将任务交给调度器Scheduler处理,threadPool.getScheduler(),这里的threadPool的实例是HystrixThreadPoolDefault

    static class HystrixThreadPoolDefault implements HystrixThreadPool {
        private final HystrixThreadPoolProperties properties;
        private final ThreadPoolExecutor threadPool;
        @Override
        public Scheduler getScheduler(Func0<Boolean> shouldInterruptThread) {
            // 根据动态配置,更新ThreadPoolExecutor的配置
            touchConfig();
            // 创建HystrixContextScheduler
            return new HystrixContextScheduler(HystrixPlugins.getInstance().getConcurrencyStrategy(), this, shouldInterruptThread);
        }
    }

    根据动态配置,更新ThreadPoolExecutor的配置

        private void touchConfig() {
            // 核心线程数
            final int dynamicCoreSize = properties.coreSize().get();
            // 配置最大线程数
            final int configuredMaximumSize = properties.maximumSize().get();
            // 根据allowMaximumSizeToDivergeFromCoreSize和coreSize和maximumSize共同决定
            // 实际的最大线程数
            int dynamicMaximumSize = properties.actualMaximumSize();
            final boolean allowSizesToDiverge = properties.getAllowMaximumSizeToDivergeFromCoreSize().get();
            // 最大线程数
            boolean maxTooLow = false;
            // 支持最大线程数 且 最大线程数小于核心线程数
            if (allowSizesToDiverge && configuredMaximumSize < dynamicCoreSize) {
                dynamicMaximumSize = dynamicCoreSize;
                maxTooLow = true;
            }
            if (threadPool.getCorePoolSize() != dynamicCoreSize || 
              (allowSizesToDiverge && threadPool.getMaximumPoolSize() != dynamicMaximumSize)) {
                if (maxTooLow) {
                    logger.error(...);
                }
                // 设置ThreadPoolExecutor
                threadPool.setCorePoolSize(dynamicCoreSize);
                threadPool.setMaximumPoolSize(dynamicMaximumSize);
            }
            // 设置空闲线程存活时间
            threadPool.setKeepAliveTime(properties.keepAliveTimeMinutes().get(), TimeUnit.MINUTES);
        }

    创建HystrixContextScheduler

        public HystrixContextScheduler(HystrixConcurrencyStrategy concurrencyStrategy, HystrixThreadPool threadPool,
                           Func0<Boolean> shouldInterruptThread) { this.concurrencyStrategy = concurrencyStrategy; this.threadPool = threadPool; this.actualScheduler = new ThreadPoolScheduler(threadPool, shouldInterruptThread); }

    2)HystrixContextScheduler执行Command

      RxJava有两个类rx.Scheduler和rx.Scheduler.Worker,这两个类都是抽象类,Scheduler负责创建Worker,Worker负责实际调度Action。

    createWorker操作ThreadPoolScheduler创建HystrixContextSchedulerWorker

    public class HystrixContextScheduler extends Scheduler {
        private final HystrixConcurrencyStrategy concurrencyStrategy;
        private final Scheduler actualScheduler;
        private final HystrixThreadPool threadPool;
        public HystrixContextScheduler(HystrixConcurrencyStrategy concurrencyStrategy, 
                  HystrixThreadPool threadPool, Func0<Boolean> shouldInterruptThread) {
            this.concurrencyStrategy = concurrencyStrategy;
            this.threadPool = threadPool;
            this.actualScheduler = new ThreadPoolScheduler(threadPool, shouldInterruptThread);
        }
        @Override
        public Worker createWorker() {
            return new HystrixContextSchedulerWorker(actualScheduler.createWorker());
        }
    }

    HystrixContextScheduler.HystrixContextSchedulerWorker.schedule(rx.functions.Action0)调度Action,实际操作WorkerHystrixContextScheduler.ThreadPoolWorker。

    private class HystrixContextSchedulerWorker extends Worker {
      private final Worker worker;
      private HystrixContextSchedulerWorker(Worker actualWorker) {
          this.worker = actualWorker;
      }
    
      @Override
      public Subscription schedule(Action0 action) {
          if (threadPool != null) {
                // 判断动态队列长度是否足够
              if (!threadPool.isQueueSpaceAvailable()) {
                  throw new RejectedExecutionException("Rejected command because thread-pool queueSize is at rejection threshold.");
              }
          }
          // HystrixContextScheduler.ThreadPoolWorker的schedule方法实际调度
          return worker.schedule(new HystrixContexSchedulerAction(concurrencyStrategy, action));
      }
    }

    HystrixThreadPool.HystrixThreadPoolDefault.isQueueSpaceAvailable判断动态队列长度是否足够

    @Override
    public boolean isQueueSpaceAvailable() {
        if (queueSize <= 0) { // 取得是maxQueueSize配置,默认-1
            return true;
        } else {
            // ThreadPoolExecutor的队列长度小于queueSizeRejectionThreshold配置的动态队列长度限制
            return threadPool.getQueue().size() < properties.queueSizeRejectionThreshold().get();
        }
    }

    ThreadPoolWorker.schedule是真正将任务提交到线程池执行的地方。

    private static class ThreadPoolWorker extends Worker {
        private final HystrixThreadPool threadPool;
        private final CompositeSubscription subscription = new CompositeSubscription();
        private final Func0<Boolean> shouldInterruptThread;
        public ThreadPoolWorker(HystrixThreadPool threadPool, Func0<Boolean> shouldInterruptThread) {
            this.threadPool = threadPool;
            this.shouldInterruptThread = shouldInterruptThread;
        }
    
        @Override
        public Subscription schedule(final Action0 action) {
            if (subscription.isUnsubscribed()) {
                return Subscriptions.unsubscribed();
            }
            ScheduledAction sa = new ScheduledAction(action);
            subscription.add(sa);
            sa.addParent(subscription);
    
            ThreadPoolExecutor executor = (ThreadPoolExecutor) threadPool.getExecutor();
            // 提交任务到线程池
            FutureTask<?> f = (FutureTask<?>) executor.submit(sa);
            sa.add(new FutureCompleterWithConfigurableInterrupt(f, shouldInterruptThread, executor));
            return sa;
        }
    }

    3)getUserExecutionObservable(_cmd)执行用户方法的地方,反射执行

        private Observable<R> getUserExecutionObservable(final AbstractCommand<R> _cmd) {
            Observable<R> userObservable;
    
            try {
                //执行
                userObservable = getExecutionObservable();
            } catch (Throwable ex) {
                userObservable = Observable.error(ex);
            }
            return userObservable
                    .lift(new ExecutionHookApplication(_cmd))
                    .lift(new DeprecatedOnRunHookApplication(_cmd));
        }
        
        final protected Observable<R> getExecutionObservable() {
            return Observable.defer(new Func0<Observable<R>>() {
                @Override
                public Observable<R> call() {
                    try {
                        //run方法对应的就是创建的command的run方法
                        return Observable.just(run());
                    } catch (Throwable ex) {
                        return Observable.error(ex);
                    }
                }
            }).doOnSubscribe(new Action0() {
                @Override
                public void call() {
                    executionThread.set(Thread.currentThread());
                }
            });
        }
        //GenericCommand
        protected Object run() throws Exception {
            LOGGER.debug("execute command: {}", getCommandKey().name());
            return process(new Action() {
                @Override
                Object execute() {
                    //反射调用原始对象的方法  MethodExecutionAction
                    return getCommandAction().execute(getExecutionType());
                }
            });
        }

    4)超时检测逻辑lift(new HystrixObservableTimeoutOperator<R>(_cmd)),通过延迟定时任务+CAS来实现超时检测。

      private static class HystrixObservableTimeoutOperator<R> implements Operator<R, R> {
    
            final AbstractCommand<R> originalCommand;
    
            public HystrixObservableTimeoutOperator(final AbstractCommand<R> originalCommand) {
                this.originalCommand = originalCommand;
            }
    
            @Override
            public Subscriber<? super R> call(final Subscriber<? super R> child) {
                final CompositeSubscription s = new CompositeSubscription();
                child.add(s);
    
                // HystrixContextRunnable让执行线程能获取到HystrixRequestContext
                final HystrixContextRunnable timeoutRunnable = new HystrixContextRunnable(originalCommand.concurrencyStrategy,
                 new Runnable() { // 触发onError @Override public void run() { child.onError(new HystrixTimeoutException()); } }); // TimerListener后续会提交到ScheduledThreadPoolExecutor中定时执行 TimerListener listener = new TimerListener() { @Override public void tick() { // 通过CAS来判断是否可以设置超时 if (originalCommand.isCommandTimedOut.compareAndSet(TimedOutStatus.NOT_EXECUTED, TimedOutStatus.TIMED_OUT)) { // 发布超时事件 originalCommand.eventNotifier.markEvent(HystrixEventType.TIMEOUT, originalCommand.commandKey); // 停止请求 s.unsubscribe(); // 执行timeoutRunnable的run方法,触发HystrixTimeoutException异常 timeoutRunnable.run(); } } //获取超时时间 @Override public int getIntervalTimeInMilliseconds() { return originalCommand.properties.executionTimeoutInMilliseconds().get(); } }; // 往定时器中添加监听器 final Reference<TimerListener> tl = HystrixTimer.getInstance().addTimerListener(listener); // originalCommand.timeoutTimer.set(tl); //创建一个新的观察者 Subscriber<R> parent = new Subscriber<R>() { @Override public void onCompleted() { if (isNotTimedOut()) { // 停止定时器 并发布成功事件 tl.clear(); child.onCompleted(); } } @Override public void onError(Throwable e) { if (isNotTimedOut()) { // 清除定时器 并发布失败事件 tl.clear(); child.onError(e); } } @Override public void onNext(R v) { // 判断超时 if (isNotTimedOut()) { child.onNext(v); } } private boolean isNotTimedOut() { // 是否完成 或者 可以修改为完成状态 return originalCommand.isCommandTimedOut.get() == TimedOutStatus.COMPLETED || originalCommand.isCommandTimedOut.compareAndSet(TimedOutStatus.NOT_EXECUTED, TimedOutStatus.COMPLETED); } }; // s.add(parent); return parent; } }

    HystrixTimer.addTimerListener提交超时检测定时任务,注意到Hystrix全局会开启一个检测超时的线程池,默认核心线程数为8,最大线程数为Integer.MAX_VALUE。

        //线程池执行器原子类
        AtomicReference<ScheduledExecutor> executor = new AtomicReference<ScheduledExecutor>();
        //添加 监听器
        public Reference<TimerListener> addTimerListener(final TimerListener listener) {
            // 初始化线程池ScheduledExecutor.initialize
            startThreadIfNeeded();
            
            Runnable r = new Runnable() {
    
                @Override
                public void run() {
                    try {
                        执行监听器的tick方法
                        listener.tick();
                    } catch (Exception e) {
                        logger.error("Failed while ticking TimerListener", e);
                    }
                }
            };
            // 延迟并间隔execution.isolation.thread.timeoutInMilliseconds时长执行,默认超时时间1秒
            ScheduledFuture<?> f = executor.get().getThreadPool()
                        .scheduleAtFixedRate(r, listener.getIntervalTimeInMilliseconds(),
                                    listener.getIntervalTimeInMilliseconds(), TimeUnit.MILLISECONDS);
            return new TimerReference(listener, f);
        }

    初始化线程池

        protected void startThreadIfNeeded() {
            // 判断是否已经存在
            while (executor.get() == null || ! executor.get().isInitialized()) {
                if (executor.compareAndSet(null, new ScheduledExecutor())) {
                    // 初始化
                    executor.get().initialize();
                }
            }
        }
        
        static class ScheduledExecutor {
            volatile ScheduledThreadPoolExecutor executor;
            private volatile boolean initialized;
            // 初始化线程池
            public void initialize() {
    
                HystrixPropertiesStrategy propertiesStrategy = HystrixPlugins.getInstance().getPropertiesStrategy();
                // hystrix.timer.threadpool.default.coreSize 默认大小为8
                int coreSize = propertiesStrategy.getTimerThreadPoolProperties().getCorePoolSize().get();
                // 线程工厂,线程名HystrixTimer-*
                ThreadFactory threadFactory = null;
                if (!PlatformSpecific.isAppEngineStandardEnvironment()) {
                    threadFactory = new ThreadFactory() {
                        final AtomicInteger counter = new AtomicInteger();
    
                        @Override
                        public Thread newThread(Runnable r) {
                            Thread thread = new Thread(r, "HystrixTimer-" + counter.incrementAndGet());
                            thread.setDaemon(true);
                            return thread;
                        }
    
                    };
                } else {
                    threadFactory = PlatformSpecific.getAppEngineThreadFactory();
                }
            // super(corePoolSize, Integer.MAX_VALUE, 0, NANOSECONDS, new DelayedWorkQueue(), threadFactory);
            // maxPoolSize无限大,非核心线程存活时间0
                executor = new ScheduledThreadPoolExecutor(coreSize, threadFactory);
                initialized = true;
            }
    
            public ScheduledThreadPoolExecutor getThreadPool() {
                return executor;
            }
    
            public boolean isInitialized() {
                return initialized;
            }
        }

    五、降级

      会走降级逻辑的情况:

    1、断路器开启 handleShortCircuitViaFallback()

    2、信号量获取失败 handleSemaphoreRejectionViaFallback()

    3、线程队列满了 handleThreadPoolRejectionViaFallback()

    4、请求超时 handleTimeoutViaFallback()

    5、请求异常 handleFailureViaFallback()

    上面这些情况都会走到同一个逻辑getFallbackOrThrowException方法,只是在这之前各种情况会做一些其他的处理,忽略他们,直接看核心逻辑就好。

    private Observable<R> getFallbackOrThrowException(final AbstractCommand<R> _cmd, final HystrixEventType eventType,
                final FailureType failureType, final String message, final Exception originalException) {
        
        ... 
        
        // fallback.enabled = true
        if (properties.fallbackEnabled().get()) {
            // 设置上下文
            final Action1<Notification<? super R>> setRequestContext = new Action1<Notification<? super R>>() {
                @Override
                public void call(Notification<? super R> rNotification) {
                    setRequestContextIfNeeded(requestContext);
                }
            };
            // onNext
            final Action1<R> markFallbackEmit = ...;
            // OnCompleted
            final Action0 markFallbackCompleted = ...;
            // 处理降级方法抛出的异常,封装一下重新抛出
            final Func1<Throwable, Observable<R>> handleFallbackError = new Func1<Throwable, Observable<R>>() {
                @Override
                public Observable<R> call(Throwable t) {
                    Exception e = originalException;
                    Exception fe = getExceptionFromThrowable(t);
                    if (fe instanceof UnsupportedOperationException) {
                        // 从子类找不到fallback时会抛出UnsupportedOperationException
                        return Observable.error(new HystrixRuntimeException(failureType, _cmd.getClass(),
                                    getLogMessagePrefix() + " " + message + " and no fallback available.", e, fe));
                    } else {
                        // 其他异常
                        return Observable.error(new HystrixRuntimeException(failureType, _cmd.getClass(),
                                    getLogMessagePrefix() + " " + message + " and fallback failed.", e, fe));
                    }
                }
            };
            // 对于fallback方法有信号量控制(fallback.isolation.semaphore.maxConcurrentRequests)
            // 默认大小为10
            final TryableSemaphore fallbackSemaphore = getFallbackSemaphore();
            final AtomicBoolean semaphoreHasBeenReleased = new AtomicBoolean(false);
            // 释放降级信号量
            final Action0 singleSemaphoreRelease = new Action0() {
                @Override
                public void call() {
                    if (semaphoreHasBeenReleased.compareAndSet(false, true)) {
                        fallbackSemaphore.release();
                    }
                }
            };
            // 降级逻辑Observable
            Observable<R> fallbackExecutionChain;
            // 获取降级信号量
            if (fallbackSemaphore.tryAcquire()) {
                try {
                    fallbackExecutionChain = getFallbackObservable();
                } catch (Throwable ex) {
                    fallbackExecutionChain = Observable.error(ex);
                }
                return fallbackExecutionChain
                        .doOnEach(setRequestContext)
                        .lift(new FallbackHookApplication(_cmd))
                        .lift(new DeprecatedOnFallbackHookApplication(_cmd))
                        .doOnNext(markFallbackEmit)
                        .doOnCompleted(markFallbackCompleted)
                        .onErrorResumeNext(handleFallbackError)
                        .doOnTerminate(singleSemaphoreRelease)
                        .doOnUnsubscribe(singleSemaphoreRelease);
            } else {
               // 处理降级的信号量获取失败,封装为Observable.error(new HystrixRuntimeException(...));
               return handleFallbackRejectionByEmittingError();
            }
        } else {
            // 处理禁用降级,封装为Observable.error(new HystrixRuntimeException(...));
            return handleFallbackDisabledByEmittingError(originalException, failureType, message);
        }
    }

    AbstractCommand.getFallbackObservable获取降级逻辑

    @Override
    final protected Observable<R> getFallbackObservable() {
        return Observable.defer(new Func0<Observable<R>>() {
            @Override
            public Observable<R> call() {
                try {
                    return Observable.just(getFallback());
                } catch (Throwable ex) {
                    return Observable.error(ex);
                }
            }
        });
    }

    HystrixCommand.getFallback默认抛出UnsupportedOperationException,需要我们自己重写降级逻辑。

    protected R getFallback() {
        throw new UnsupportedOperationException("No fallback available.");
    }

    有一些异常是不会走fallback降级逻辑的

    1、HystrixBadRequestException,我们可以手动抛出这个异常,让方法不走降级逻辑

    throw new HystrixBadRequestException("此异常不走降级");

    原理

                    //executeCommandAndObserve方法,降级逻辑处理handleFallback
                    Exception e = getExceptionFromThrowable(t);
                    executionResult = executionResult.setExecutionException(e);
                    if (e instanceof RejectedExecutionException) {
                        return handleThreadPoolRejectionViaFallback(e);
                    } else if (t instanceof HystrixTimeoutException) {
                        return handleTimeoutViaFallback();
                        //HystrixBadRequestException异常不走fallback逻辑
                    } else if (t instanceof HystrixBadRequestException) {
                        return handleBadRequestByEmittingError(e);
                    } else {
                        //HystrixBadRequestException异常不走fallback逻辑
                        if (e instanceof HystrixBadRequestException) {
                            eventNotifier.markEvent(HystrixEventType.BAD_REQUEST, commandKey);
                            return Observable.error(e);
                        }
    
                        return handleFailureViaFallback(e);
                    }

    2、自定义异常,必须实现ExceptionNotWrappedByHystrix接口,然后抛出

    public class MyHystrixException extends RuntimeException implements ExceptionNotWrappedByHystrix {
    
        public MyHystrixException(String message){
            super(message);
        }
    }

    原理

            //getFallbackOrThrowException方法
            if (shouldNotBeWrapped(originalException)){
                Exception e = wrapWithOnErrorHook(failureType, originalException);
                return Observable.error(e);
            }
            protected boolean shouldNotBeWrapped(Throwable underlying) {
                return underlying instanceof ExceptionNotWrappedByHystrix;
            }

    3、isUnrecoverable判断异常的cause是不是不可恢复的。比如栈溢出、虚拟机异常、线程终止。

         //getFallbackOrThrowException方法
        private boolean isUnrecoverable(Throwable t) {
            if (t != null && t.getCause() != null) {
                Throwable cause = t.getCause();
                if (cause instanceof StackOverflowError) {
                    return true;
                } else if (cause instanceof VirtualMachineError) {
                    return true;
                } else if (cause instanceof ThreadDeath) {
                    return true;
                } else if (cause instanceof LinkageError) {
                    return true;
                }
            }
            return false;
        }

    参考连接:https://juejin.cn/column/6960847703521624094 

  • 相关阅读:
    C#调试信息打印到输出窗口
    C#拼接SQL中in条件
    从图像到知识:深度神经网络实现图像理解的原理解析
    Cocoa Touch(六):App运行机制 NSRunLoop, KVC, KVO, Notification, ARC
    Cocoa Touch(五):网络请求 NSURLSession/AFNetworking, GCD, NSURLResquest
    JQuery:选择器、动画、AJAX请求
    Cocoa Touch(四): 多线程GCD, NSObject, NSThread, NSOperationQueue
    Socket、RPC通信实例,简单版本,仅供查阅
    Cocoa Touch(三):图形界面UIKit、Core Animation、Core Graphics
    Cocoa Touch(二):数据存储CoreData, NSKeyArchiver, NSOutputStream, NSUserDefaults
  • 原文地址:https://www.cnblogs.com/sglx/p/15784595.html
Copyright © 2011-2022 走看看