序
本文主要研究一下resilience4j的CircuitBreakerConfig
CircuitBreakerConfig
resilience4j-circuitbreaker-0.13.0-sources.jar!/io/github/resilience4j/circuitbreaker/CircuitBreakerConfig.java
/** * A {@link CircuitBreakerConfig} configures a {@link CircuitBreaker} */public class CircuitBreakerConfig { public static final int DEFAULT_MAX_FAILURE_THRESHOLD = 50; // Percentage public static final int DEFAULT_WAIT_DURATION_IN_OPEN_STATE = 60; // Seconds public static final int DEFAULT_RING_BUFFER_SIZE_IN_HALF_OPEN_STATE = 10; public static final int DEFAULT_RING_BUFFER_SIZE_IN_CLOSED_STATE = 100; public static final PredicateDEFAULT_RECORD_FAILURE_PREDICATE = (throwable) -> true; private float failureRateThreshold = DEFAULT_MAX_FAILURE_THRESHOLD; private int ringBufferSizeInHalfOpenState = DEFAULT_RING_BUFFER_SIZE_IN_HALF_OPEN_STATE; private int ringBufferSizeInClosedState = DEFAULT_RING_BUFFER_SIZE_IN_CLOSED_STATE; private Duration waitDurationInOpenState = Duration.ofSeconds(DEFAULT_WAIT_DURATION_IN_OPEN_STATE); // The default exception predicate counts all exceptions as failures. private Predicate recordFailurePredicate = DEFAULT_RECORD_FAILURE_PREDICATE; private boolean automaticTransitionFromOpenToHalfOpenEnabled = false; //......}
这里涉及了几个参数如下:
- failureRateThreshold,默认为50,即失败率阈值为50%
- ringBufferSizeInHalfOpenState,设置当断路器处于HALF_OPEN状态下的ring buffer的大小,它存储了最近一段时间请求的成功失败状态,默认为10
- ringBufferSizeInClosedState,设置当断路器处于CLOSED状态下的ring buffer的大小,它存储了最近一段时间请求的成功失败状态,默认为100
- waitDurationInOpenState,用来指定断路器从OPEN到HALF_OPEN状态等待的时长,默认是60秒
- recordFailurePredicate,用于判断哪些异常应该算作失败纳入断路器统计,默认是Throwable类型
- automaticTransitionFromOpenToHalfOpenEnabled,当waitDurationInOpenState时间一过,是否自动从OPEN切换到HALF_OPEN,默认为true
CircuitBreakerMetrics
resilience4j-circuitbreaker-0.13.0-sources.jar!/io/github/resilience4j/circuitbreaker/internal/CircuitBreakerMetrics.java
class CircuitBreakerMetrics implements CircuitBreaker.Metrics { private final int ringBufferSize; private final RingBitSet ringBitSet; private final LongAdder numberOfNotPermittedCalls; CircuitBreakerMetrics(int ringBufferSize) { this(ringBufferSize, null); } CircuitBreakerMetrics(int ringBufferSize, RingBitSet sourceSet) { this.ringBufferSize = ringBufferSize; if(sourceSet != null) { this.ringBitSet = new RingBitSet(this.ringBufferSize, sourceSet); }else{ this.ringBitSet = new RingBitSet(this.ringBufferSize); } this.numberOfNotPermittedCalls = new LongAdder(); } /** * Creates a new CircuitBreakerMetrics instance and copies the content of the current RingBitSet * into the new RingBitSet. * * @param targetRingBufferSize the ringBufferSize of the new CircuitBreakerMetrics instances * @return a CircuitBreakerMetrics */ public CircuitBreakerMetrics copy(int targetRingBufferSize) { return new CircuitBreakerMetrics(targetRingBufferSize, this.ringBitSet); } /** * Records a failed call and returns the current failure rate in percentage. * * @return the current failure rate in percentage. */ float onError() { int currentNumberOfFailedCalls = ringBitSet.setNextBit(true); return getFailureRate(currentNumberOfFailedCalls); } /** * Records a successful call and returns the current failure rate in percentage. * * @return the current failure rate in percentage. */ float onSuccess() { int currentNumberOfFailedCalls = ringBitSet.setNextBit(false); return getFailureRate(currentNumberOfFailedCalls); } /** * Records a call which was not permitted, because the CircuitBreaker state is OPEN. */ void onCallNotPermitted() { numberOfNotPermittedCalls.increment(); } /** * {@inheritDoc} */ @Override public float getFailureRate() { return getFailureRate(getNumberOfFailedCalls()); } /** * {@inheritDoc} */ @Override public int getMaxNumberOfBufferedCalls() { return ringBufferSize; } /** * {@inheritDoc} */ @Override public int getNumberOfSuccessfulCalls() { return getNumberOfBufferedCalls() - getNumberOfFailedCalls(); } /** * {@inheritDoc} */ @Override public int getNumberOfBufferedCalls() { return this.ringBitSet.length(); } /** * {@inheritDoc} */ @Override public long getNumberOfNotPermittedCalls() { return this.numberOfNotPermittedCalls.sum(); } /** * {@inheritDoc} */ @Override public int getNumberOfFailedCalls() { return this.ringBitSet.cardinality(); } private float getFailureRate(int numberOfFailedCalls) { if (getNumberOfBufferedCalls() < ringBufferSize) { return -1.0f; } return numberOfFailedCalls * 100.0f / ringBufferSize; }}
- ringBitSet.setNextBit方法返回的是这个ringBitSet中被设置为true的个数,这里就是numberOfFailedCalls
- getFailureRate里头先判断,如果ringBitSet中的个数没有达到ringBufferSize指定的大小,则返回-1.0f,则不计算失败率
- 失败率的计算就是numberOfFailedCalls * 100.0f / ringBufferSize
RingBitSet
resilience4j-circuitbreaker-0.13.0-sources.jar!/io/github/resilience4j/circuitbreaker/internal/RingBitSet.java
/** * A ring bit set which stores bits up to a maximum size of bits. */class RingBitSet { private final int size; private final BitSetMod bitSet; private boolean notFull; private int index = -1; private volatile int length; private volatile int cardinality = 0; //...... /** * Sets the bit at the next index to the specified value. * * @param value a boolean value to set * @return the number of bits set to {@code true} */ public synchronized int setNextBit(boolean value) { increaseLength(); index = (index + 1) % size; int previous = bitSet.set(index, value); int current = value ? 1 : 0; cardinality = cardinality - previous + current; return cardinality; } private void increaseLength() { if (notFull) { int nextLength = length + 1; if (nextLength < size) { length = nextLength; } else { length = size; notFull = false; } } }}
- 重点看setNextBit方法,这里的cardinality就是ringbuffer中设置为true的个数
- increaseLength方法,如果length不超过size则递增,超过则重置为size大小,即最大为size大小,然后用notFull标记是否满
HalfOpenState
resilience4j-circuitbreaker-0.13.0-sources.jar!/io/github/resilience4j/circuitbreaker/internal/HalfOpenState.java
final class HalfOpenState extends CircuitBreakerState { private CircuitBreakerMetrics circuitBreakerMetrics; private final float failureRateThreshold; HalfOpenState(CircuitBreakerStateMachine stateMachine) { super(stateMachine); CircuitBreakerConfig circuitBreakerConfig = stateMachine.getCircuitBreakerConfig(); this.circuitBreakerMetrics = new CircuitBreakerMetrics( circuitBreakerConfig.getRingBufferSizeInHalfOpenState()); this.failureRateThreshold = stateMachine.getCircuitBreakerConfig().getFailureRateThreshold(); } /** * Returns always true, because the CircuitBreaker is half open. * * @return always true, because the CircuitBreaker is half open. */ @Override boolean isCallPermitted() { return true; } @Override void onError(Throwable throwable) { // CircuitBreakerMetrics is thread-safe checkFailureRate(circuitBreakerMetrics.onError()); } @Override void onSuccess() { // CircuitBreakerMetrics is thread-safe checkFailureRate(circuitBreakerMetrics.onSuccess()); } /** * Checks if the current failure rate is above or below the threshold. * If the failure rate is above the threshold, transition the state machine to OPEN state. * If the failure rate is below the threshold, transition the state machine to CLOSED state. * * @param currentFailureRate the current failure rate */ private void checkFailureRate(float currentFailureRate) { if(currentFailureRate != -1){ if(currentFailureRate >= failureRateThreshold) { stateMachine.transitionToOpenState(); }else{ stateMachine.transitionToClosedState(); } } } /** * Get the state of the CircuitBreaker */ @Override CircuitBreaker.State getState() { return CircuitBreaker.State.HALF_OPEN; } @Override CircuitBreakerMetrics getMetrics() { return circuitBreakerMetrics; }}
- 这里的ringBufferSize为getRingBufferSizeInHalfOpenState
- 这里onError以及onSuccess都会触发checkFailureRate,检查失败率是否达到阈值
- checkFailureRate判断的时候首先排除掉-1.0f,然后如果达到阈值,则将状态切换到OPEN,不达到阈值则切换到CLOSED状态
ClosedState
resilience4j-circuitbreaker-0.13.0-sources.jar!/io/github/resilience4j/circuitbreaker/internal/ClosedState.java
final class ClosedState extends CircuitBreakerState { private final CircuitBreakerMetrics circuitBreakerMetrics; private final float failureRateThreshold; ClosedState(CircuitBreakerStateMachine stateMachine) { this(stateMachine, null); } ClosedState(CircuitBreakerStateMachine stateMachine, CircuitBreakerMetrics circuitBreakerMetrics) { super(stateMachine); CircuitBreakerConfig circuitBreakerConfig = stateMachine.getCircuitBreakerConfig(); if(circuitBreakerMetrics == null){ this.circuitBreakerMetrics = new CircuitBreakerMetrics( circuitBreakerConfig.getRingBufferSizeInClosedState()); }else{ this.circuitBreakerMetrics = circuitBreakerMetrics.copy(circuitBreakerConfig.getRingBufferSizeInClosedState()); } this.failureRateThreshold = stateMachine.getCircuitBreakerConfig().getFailureRateThreshold(); } /** * Returns always true, because the CircuitBreaker is closed. * * @return always true, because the CircuitBreaker is closed. */ @Override boolean isCallPermitted() { return true; } @Override void onError(Throwable throwable) { // CircuitBreakerMetrics is thread-safe checkFailureRate(circuitBreakerMetrics.onError()); } @Override void onSuccess() { // CircuitBreakerMetrics is thread-safe checkFailureRate(circuitBreakerMetrics.onSuccess()); } /** * Checks if the current failure rate is above the threshold. * If the failure rate is above the threshold, transitions the state machine to OPEN state. * * @param currentFailureRate the current failure rate */ private void checkFailureRate(float currentFailureRate) { if (currentFailureRate >= failureRateThreshold) { // Transition the state machine to OPEN state, because the failure rate is above the threshold stateMachine.transitionToOpenState(); } } /** * Get the state of the CircuitBreaker */ @Override CircuitBreaker.State getState() { return CircuitBreaker.State.CLOSED; } /** * * Get metrics of the CircuitBreaker */ @Override CircuitBreakerMetrics getMetrics() { return circuitBreakerMetrics; }}
- 这里的ringBufferSize为getRingBufferSizeInClosedState
- 这里onError以及onSuccess都会触发checkFailureRate,检查失败率是否达到阈值
- checkFailureRate判断如果大于设定的阈值,则把状态变为OPEN
小结
- resilience4j的CircuitBreakerConfig主要设置了failureRateThreshold、ringBufferSizeInHalfOpenState、ringBufferSizeInClosedState、waitDurationInOpenState、recordFailurePredicate、automaticTransitionFromOpenToHalfOpenEnabled这几个配置。
- ringBufferSizeInHalfOpenState、ringBufferSizeInClosedState设置的是在ringbuffer的大小,同时也影响failureRate的计算,即如果ringbuffer中的长度小于这个大小,则不会计算失败率。
- ringbuffer中的length会递增,但是不会超过指定的大小,最大为指定的size