本文主要研究一下resilience4j的CircuitBreakerConfigjava
resilience4j-circuitbreaker-0.13.0-sources.jar!/io/github/resilience4j/circuitbreaker/CircuitBreakerConfig.javagit
/** * 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 Predicate<Throwable> DEFAULT_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<Throwable> recordFailurePredicate = DEFAULT_RECORD_FAILURE_PREDICATE; private boolean automaticTransitionFromOpenToHalfOpenEnabled = false; //...... }
這裏涉及了幾個參數以下:
resilience4j-circuitbreaker-0.13.0-sources.jar!/io/github/resilience4j/circuitbreaker/internal/CircuitBreakerMetrics.javagithub
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; } }
resilience4j-circuitbreaker-0.13.0-sources.jar!/io/github/resilience4j/circuitbreaker/internal/RingBitSet.javaide
/** * 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; } } } }
resilience4j-circuitbreaker-0.13.0-sources.jar!/io/github/resilience4j/circuitbreaker/internal/HalfOpenState.javaui
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; } }
resilience4j-circuitbreaker-0.13.0-sources.jar!/io/github/resilience4j/circuitbreaker/internal/ClosedState.javathis
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; } }