resilience4j(六):核心模块CircuitBreaker源码之CircuitBreakerMetrics

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

CircuitBreakerMetrics

熔断器度量指标,熔断器在工作中,熔断相关实际数据,均存储在此。

类图关系如下:

成员变量

private final int ringBufferSize;//熔断在CLOSED,HALF_OPEN状态下的环形区缓冲大小
private final RingBitSet ringBitSet;//存储请求通过或被熔断次数
private final LongAdder numberOfNotPermittedCalls;//请求被熔断的次数

RingBitSet

CircuitBreaker在CLOSED 或 HALF_OPEN状态时,成功调用会在bit位存0,失败的调用会存储1。Ring Bit Buffer具有(可配置的)固定大小。Ring Bit Buffer 原理类似于java.util.BitSet。BitSet使用long []数组来存储这些位,意味着BitSet只需要一个16个长(64位)的long型数组就可存储1024个请求的调用状态。

在计算失败率之前,环位缓冲器必须已满。
例如,如果环形缓冲区的大小为10,则必须至少有10次请求,然后才能计算失败率。如果只请求了9次,哪怕9次都失败,CircuitBreaker也不会切换至OPEN状态。

在等待一段时间后,CircuitBreaker状态从OPEN → HALF_OPEN,并允许请求调用以观察后续请求是否仍然不可用或已再次可用。CircuitBreaker使用另一个(可配置的)环位缓冲区来评估HALF_OPEN状态中的失败率。如果失败率高于配置的阈值,则状态将更改回OPEN。如果失败率低于或等于阈值,则状态变回CLOSED。
CircuitBreaker::onError检查是否应将异常记录为失败或应忽略。可以配置自定义Predicate,以确定是否应将异常记录为失败。默认将所有异常记录为失败。

CircuitBreaker支持重置为原始状态(circuitBreaker::reset),丢失所有指标并重置其Ring Bit Buffer。

从截图中可以看出,请求成功时,setNextBit返回值不变,请求失败时,setNextBit返回值+1,从而可以得出setNextBit返回的是失败次数的结论,且该方法thread-safe。

public synchronized int setNextBit(boolean value) {
    	//调用次数+1
        increaseLength();
        index = (index + 1) % size;
		//更新位值
        int previous = bitSet.set(index, value);
        int current = value ? 1 : 0;
        cardinality = cardinality - previous + current;
        //失败请求对应的number
        return cardinality;
    }
    
	//通俗的可以理解成比如设置环形缓冲区长度为10,则前9次,单纯调用次数length + 1,第10次,length为0,后续不再增加调用次数
    private void increaseLength() {
        if (notFull) {
        	//计算至本次总调用次数
            int nextLength = length + 1;
            if (nextLength < size) {
	            //容量没满,总调用次数+1
                length = nextLength;
            } else {
                length = size;
                notFull = false;
            }
        }
    }

总结:

  • RingBitSet::length 表示总请求次数
  • RingBitSet::setNextBit:(更新RingBitSet::cardinality)表示失败次数
  • 请求成功次数 = RingBitSet::length - RingBitSet::cardinality

检查阀值

private float getFailureRate(int numberOfFailedCalls) {
    	//当总调用次数未达到环形缓冲区size时,暂不进行熔断检查
        if (getNumberOfBufferedCalls() < ringBufferSize) {
            return -1.0f;
        }
        //失败率 = 失败次数/环形缓冲区size * 100%
        return numberOfFailedCalls * 100.0f / ringBufferSize;
    }

相关文章