博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
聊聊resilience4j的CircuitBreakerConfig
阅读量:5763 次
发布时间:2019-06-18

本文共 11631 字,大约阅读时间需要 38 分钟。

本文主要研究一下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 Predicate
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
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

doc

转载地址:http://dpwux.baihongyu.com/

你可能感兴趣的文章
Magento XML cheatsheet
查看>>
Egg 2.19.0 发布,阿里开源的企业级 Node.js 框架
查看>>
Kubernetes 弹性伸缩全场景解析 (四)- 让核心组件充满弹性 ...
查看>>
使用MySQLTuner-perl对MySQL进行优化
查看>>
Swoole 4.1.0 正式版发布,支持原生 Redis/PDO/MySQLi 协程化 ...
查看>>
开发网络视频直播系统需要注意的地方
查看>>
haproxy mysql实例配置
查看>>
强化学习的未来— 第一部分
查看>>
TableStore:用户画像数据的存储和查询利器
查看>>
2019 DockerCon 大会即将召开,快来制定您的专属议程吧!
查看>>
15分钟构建超低成本数据大屏:DataV + DLA
查看>>
1月9日云栖精选夜读 | Mars 算法实践——人脸识别
查看>>
SparkSQL Catalyst解析
查看>>
jSearch(聚搜) 1.0.0 终于来了
查看>>
盘点2018云计算市场,变化大于需求?
查看>>
极光推送(一)集成
查看>>
MySQL 8.0 压缩包版安装方法
查看>>
@Transient注解输出空间位置属性
查看>>
Ansible-playbook 条件判断when、pause(学习笔记二十三)
查看>>
5种你未必知道的JavaScript和CSS交互的方法(转发)
查看>>