resilience4j(四):核心模块CircuitBreaker源码之CircuitBreakerStateMachine

x33g5p2x  于2022-03-22 转载在 其他  
字(4.1k)|赞(0)|评价(0)|浏览(538)

CircuitBreakerStateMachine

熔断器有限状态器,熔断器核心接口CircuitBreaker的实现类。

先看一段CircuitBreaker 默认接口实现代码

static <T> Supplier<T> decorateSupplier(CircuitBreaker circuitBreaker, Supplier<T> supplier){
        return () -> {
            //判断是否允许请求通过,不通过,抛出CircuitBreakerOpenException
            CircuitBreakerUtils.isCallPermitted(circuitBreaker);
            long start = System.nanoTime();
            try {
            	//反射执行业务代码,并返回结果
                T returnValue = supplier.get();
                long durationInNanos = System.nanoTime() - start;
                //请求处理成功,触发熔断器成功处理策略
                circuitBreaker.onSuccess(durationInNanos);
                return returnValue;
            } catch (Exception exception) {
                // Do not handle java.lang.Error
                long durationInNanos = System.nanoTime() - start;
                //请求出现异常,触发熔断器error处理策略
                circuitBreaker.onError(durationInNanos, exception);
                throw exception;
            }
        };
    }

CircuitBreaker装饰请求默认实现大同小异,熔断大体处理流程见下图:

状态转换图

有限状态机主要是在CLOSED、OPEN、HALF_OPEN三者之间转换,另外还有两种特殊状态: DISABLED、FORCED_OPEN。

- CLOSED → OPEN
 熔断器默认初始为CLOSED状态,当请求失败率达到failureRateThreshold阀值后,熔断器处于OPEN状态,不允许所有请求通过。
- OPEN → HALF_OPEN
 熔断器在处于OPEN状态后,等待waitDurationInOpenState时长后,熔断器转换到HALF_OPEN状态,允许部分请求通过。
- HALF_OPEN →OPEN
 熔断器处于HALF_OPEN状态时,当请求次数达到ringBufferSizeInHalfOpenState后,判断请求失败率是否依旧超过failureRateThreshold阀值,若超过,熔断器则回到OPEN状态。
- HALF_OPEN →CLOSED
 熔断器处于HALF_OPEN状态时,当请求次数达到ringBufferSizeInHalfOpenState后,判断请求失败率是否依旧超过failureRateThreshold阀值,若小于阀值,熔断器转换到CLOSED状态。

状态转换接口源码

//熔断器切换到不可用状态
	public void transitionToDisabledState() {
        stateTransition(DISABLED, currentState -> new DisabledState(this));
    }
    
   //熔断器切换到强制开启状态
    public void transitionToForcedOpenState() {
        stateTransition(FORCED_OPEN, currentState -> new ForcedOpenState(this));
    }

    //熔断器切换到关闭状态
    public void transitionToClosedState() {
        stateTransition(CLOSED, currentState -> new ClosedState(this, currentState.getMetrics()));
    }

    //熔断器切换到开启状态
    public void transitionToOpenState() {
        stateTransition(OPEN, currentState -> new OpenState(this, currentState.getMetrics()));
    }

    //熔断器切换到半开状态
    public void transitionToHalfOpenState() {
        stateTransition(HALF_OPEN, currentState -> new HalfOpenState(this));
    }
    
    //熔断器熔断状态转换
    private void stateTransition(State newState, Function<CircuitBreakerState, CircuitBreakerState> newStateGenerator) {
        CircuitBreakerState previousState = stateReference.getAndUpdate(currentState -> {
        	//若当前状态与更新状态一样,则返回
            if (currentState.getState() == newState) {
                return currentState;
            }
            //若当前状态与更新状态不一样,切换到新状态
            return newStateGenerator.apply(currentState);
        });
        //状态发生了变化,则发布状态转换事件。evenType为:Type.STATE_TRANSITION
        if (previousState.getState() != newState) {
            publishStateTransitionEvent(StateTransition.transitionBetween(previousState.getState(), newState));
        }
    }

从源码可以看出状态转换通过AtomicReference来保证原子操作,从而实现thread-safe。

核心流程接口介绍

isCallPermitted(判断请求是否允许通过)

有限状态机是通过 AtomicReference<CircuitBreakerState> stateReference 保证状态转换实现线程安全。

public boolean isCallPermitted() {
    	//判断是否允许请求通过
        boolean callPermitted = stateReference.get().isCallPermitted();
        if (!callPermitted) {
        	//不允许,发布请求不允许被调用事件
            publishCallNotPermittedEvent();
        }
        return callPermitted;
    }

onSuccess(请求调用成功处理策略)

public void onSuccess(long durationInNanos) {
    	//发布成功事件
        publishSuccessEvent(durationInNanos);
        //更新熔断指标
        stateReference.get().onSuccess();
    }

onError(请求调用失败即出现异常处理策略)

public void onError(long durationInNanos, Throwable throwable) {
        // Handle the case if the completable future throw CompletionException wrapping the original exception
        // where original exception is the the one to retry not the CompletionException.
        Predicate<Throwable> recordFailurePredicate = circuitBreakerConfig.getRecordFailurePredicate();
        if (throwable instanceof CompletionException) {
        	//如果是异步异常,获取原始异常
            Throwable cause = throwable.getCause();
            handleThrowable(durationInNanos, recordFailurePredicate, cause);
        }else{
            handleThrowable(durationInNanos, recordFailurePredicate, throwable);
        }
    }
    private void handleThrowable(long durationInNanos, Predicate<Throwable> recordFailurePredicate, Throwable throwable) {
    	//根据配置check是忽略该次请求的异常,还是计入失败并增加失败率
        if (recordFailurePredicate.test(throwable)) {
            LOG.debug("CircuitBreaker '{}' recorded a failure:", name, throwable);
            publishCircuitErrorEvent(name, durationInNanos, throwable);
            stateReference.get().onError(throwable);
        } else {
            publishCircuitIgnoredErrorEvent(name, durationInNanos, throwable);
        }
    }

从源码可知,熔断器是根据业务代码通俗的说是根据业务method是否抛出异常来决定处理逻辑,同时根据异常及熔断配置,来判定是否做熔断处理,还是忽略本次异常请求。
若异常为配置中可忽略异常,则本次请求不做任何失败处理,也不更新熔断指标,只发布CircuitBreakerOnIgnoredErrorEvent。

CircuitBreakerState会在后续章节讲解

相关文章