CircuitBreaker有5种状态,把这5种状态的公共属性和行为抽象到CircuitBreakerState,然后5种状态ClosedState、OpenState、DisabledState、ForcedOpenState、HalfOpenState分别去实现各自的行为
其中公共行为有:
//把5种状态的公共属性及公共行为抽象出来封装成抽象类CircuitBreakerState
private interface CircuitBreakerState {
//是否可以尝试获取信号量,其实就是一个AtomicBoolean变量
boolean tryAcquirePermission();
//获取信号量,根据是否获取信号量来作为是否允许请求调用后端接口的判断
//close没有实现
//open,halfOpen,ForcedOpen:如果仍是open状态并请求,直接报错
void acquirePermission();
// 释放信号量
//close,open ,ForcedOpen没有实现
//HalfOpen,将permittedNumberOfCalls+1 ???
void releasePermission();
//请求调用失败,记录指标,当达到设定的度量指标后,调用状态机实例触发状态转换
//1.先记录请求,即把对应的总请求次数,错误请求次数等+1,再计算错误率/慢调用率等是否达到阈值 (记录请求是AbstractAggregation实现,计算错误率等是CircuitBreakerMetrics计算的,后面讲到)
//2. 根据result是否达到阈值结果,若是,则调用stateTransition更改状态
void onError(long duration, TimeUnit durationUnit, Throwable throwable);
//请求调用成功,记录指标,当达到设定的度量指标后,调用状态机实例触发状态转换
void onSuccess(long duration, TimeUnit durationUnit);
int attempts();
//返回当前circuitBreaker的状态
CircuitBreaker.State getState();
//返回当前状态的封装了度量指标的类实例
CircuitBreakerMetrics getMetrics();
/**
* Should the CircuitBreaker in this state publish events
* 是否要发布事件(先看是否设置了强制发布事件或允许发布)
* @return a boolean signaling if the events should be published
*/
default boolean shouldPublishEvents(CircuitBreakerEvent event) {
return event.getEventType().forcePublish || getState().allowPublish;
}
}
automaticTransitionFromOpenToHalfOpenEnabled: true
,则需要 OpenState(final int attempts, CircuitBreakerMetrics circuitBreakerMetrics) {
this.attempts = attempts;
final long waitDurationInMillis = circuitBreakerConfig
.getWaitIntervalFunctionInOpenState().apply(attempts);
this.retryAfterWaitDuration = clock.instant().plus(waitDurationInMillis, MILLIS);
this.circuitBreakerMetrics = circuitBreakerMetrics;
if (circuitBreakerConfig.isAutomaticTransitionFromOpenToHalfOpenEnabled()) {
//如果设置了自动 从开开到半开 ,则需要设置一个 waitDurationInOpenState秒之后的守候线程去将状态从打开改为半开
ScheduledExecutorService scheduledExecutorService = schedulerFactory.getScheduler();
//调用 OpenStat的toHalfOpenState()更改状态为半开
scheduledExecutorService
.schedule(this::toHalfOpenState, waitDurationInMillis, TimeUnit.MILLISECONDS);
}
isOpen = new AtomicBoolean(true);
}
/**
* 状态的枚举类型
* 为了方便进行判等操作,同时也设置了每种状态是否允许发布事件
* States of the CircuitBreaker state machine.
*/
enum State {
//是否允许发布事件
public final boolean allowPublish;
private final int order;
。。。。
State(int order, boolean allowPublish) {
this.order = order;
this.allowPublish = allowPublish;
}
}
/**
* State transitions of the CircuitBreaker state machine.
* 有限状态机所有可能发生的状态转换,主要用于在状态转换事件中表示哪两种状态发生了转换
*/
enum StateTransition {
。。。
// 提供方法根据两个状态返回状态转换的枚举
public static StateTransition transitionBetween(String name, State fromState,
State toState) {
final StateTransition stateTransition = STATE_TRANSITION_MAP
.get(Tuple.of(fromState, toState));
if (stateTransition == null) {
throw new IllegalStateTransitionException(name, fromState, toState);
}
return stateTransition;
}
//可以利用此方法,不经过注册中心,直接创建名为name,配置为默认配置的熔断器
static CircuitBreaker ofDefaults(String name) {
return new CircuitBreakerStateMachine(name);
}
// 直接创建名为name,指定配置的熔断器
static CircuitBreaker of(String name, CircuitBreakerConfig circuitBreakerConfig) {
return new CircuitBreakerStateMachine(name, circuitBreakerConfig);
}
static CircuitBreaker of(String name, CircuitBreakerConfig circuitBreakerConfig,
io.vavr.collection.Map tags) {
return new CircuitBreakerStateMachine(name, circuitBreakerConfig, tags);
}
//直接创建名为name,指定配置的熔断器,使用java的supplier
static CircuitBreaker of(String name,
Supplier circuitBreakerConfigSupplier) {
return new CircuitBreakerStateMachine(name, circuitBreakerConfigSupplier);
}
static CircuitBreaker of(String name,
Supplier circuitBreakerConfigSupplier,
io.vavr.collection.Map tags) {
return new CircuitBreakerStateMachine(name, circuitBreakerConfigSupplier, tags);
}
CircuitBreaker.decorateCheckedSupplier() / CircuitBreaker.decorateCheckedRunnable() / CircuitBreaker.decorateCheckedFunction()
装饰 Supplier / Runnable / Function / CheckedRunnable / CheckedFunction,然后使用Vavr的Try.of(…) / Try.run(…) 调用被装饰的函数,我们项目就利用了此功能,也可以使用map / flatMap / filter / recover / andThen链接更多的函数。函数链只有在熔断器处于关闭或半开状态时才可以被调用介绍其一decorateSupplier()方法: static Supplier decorateSupplier(CircuitBreaker circuitBreaker, Supplier supplier) {
return () -> {
//获取信号量,调用顺序 CircuitBreakerStateMachine.acquirePermission ->CircuitBreakerState.acquirePermission
circuitBreaker.acquirePermission();
long start = System.nanoTime();
try {
//执行被装饰的方法
T returnValue = supplier.get();
long durationInNanos = System.nanoTime() - start;
//调用成功:记录请求,发布事件
//调用顺序 CircuitBreakerStateMachine.onSuccess ->CircuitBreakerState.onSuccess
circuitBreaker.onSuccess(durationInNanos, TimeUnit.NANOSECONDS);
return returnValue;
} catch (Exception exception) {
// Do not handle java.lang.Error
long durationInNanos = System.nanoTime() - start;
//调用失败,根据是否记录异常,行为不同
//调用顺序 CircuitBreakerStateMachine.onError ->CircuitBreakerState.handleThrowable
circuitBreaker.onError(durationInNanos, TimeUnit.NANOSECONDS, exception);
throw exception;
}
};
}
上面提到状态已经创建好,但是状态之间是如何转换的,封装了CircuitBreakerStateMachine来实现,它实现了CircuitBreaker接口,实现的功能包括
//状态转换公共逻辑方法
private void stateTransition(State newState,
UnaryOperator newStateGenerator) {
//先获取当前状态,然后执行状态更新方法
CircuitBreakerState previousState = stateReference.getAndUpdate(currentState -> {
//获取 状态转换的枚举
StateTransition.transitionBetween(getName(), currentState.getState(), newState);
//更新为新状态
return newStateGenerator.apply(currentState);
});
//得到状态转换的枚举值,再查看是否设置了强制发布事件/允许发布事件,如果是,则发布状态转换事件
publishStateTransitionEvent(
StateTransition.transitionBetween(getName(), previousState.getState(), newState));
}
private void handleThrowable(long duration, TimeUnit durationUnit, Throwable throwable) {
//判断请求调用抛出的异常是否需要记录,默认所有异常都需要记录
if (circuitBreakerConfig.getIgnoreExceptionPredicate().test(throwable)) {
//不需要记录异常
LOG.debug("CircuitBreaker '{}' ignored an exception:", name, throwable);
//(只有HalfOpenStat才有实现,将通过数+1,因为次异常不需要记录,忽略了)
releasePermission();
//发布忽略异常事件
publishCircuitIgnoredErrorEvent(name, duration, durationUnit, throwable);
} else if (circuitBreakerConfig.getRecordExceptionPredicate().test(throwable)) {
//需要记录异常
LOG.debug("CircuitBreaker '{}' recorded an exception as failure:", name, throwable);
//发布请求失败事件
publishCircuitErrorEvent(name, duration, durationUnit, throwable);
//调用当前状态CircuitBreakerState的onError()
stateReference.get().onError(duration, durationUnit, throwable);
} else {
LOG.debug("CircuitBreaker '{}' recorded an exception as success:", name, throwable);
//不是异常,就是正常请求,发布成功事件
publishSuccessEvent(duration, durationUnit);
//记录指标
stateReference.get().onSuccess(duration, durationUnit);
}
}
CircuitBreaker采用装饰器模式,这也正是Resilience4j 框架的一大亮点,可以根据自己的需求,添加自己想要实现的功能,StateMachine主要负责CircuitBreakerState的转换