vertx

Vertx - RollingCounter

2019-08-25  本文已影响0人  pjqq

源码坐标:package io.vertx.circuitbreaker.impl.CircuitBreakerImpl中内部类,是断路器Circuit Breaker中的循环计数器。
使用场景:Circuit Breaker通过统计时间窗口内的请求失败次数,如果超出阈值,则判定请求对象已无效,给予“熔断”。RollingCounter承担主要功能。

1.CircuitBreakerOptions设定阈值。

private static final int DEFAULT_FAILURES_ROLLING_WINDOW = 10000;
private long failuresRollingWindow = DEFAULT_FAILURES_ROLLING_WINDOW;

public CircuitBreakerOptions setFailuresRollingWindow(long failureRollingWindow) {
    this.failuresRollingWindow = failureRollingWindow;
    return this;
  }

2.创建失败循环计数。

this.rollingFailures = new RollingCounter(options.getFailuresRollingWindow() / 1000, TimeUnit.SECONDS);

3.RollingCounter

  public static class RollingCounter {
    private Map<Long, Long> window;
    private long timeUnitsInWindow;
    private TimeUnit windowTimeUnit;

    public RollingCounter(long timeUnitsInWindow, TimeUnit windowTimeUnit) {
      this.windowTimeUnit = windowTimeUnit;
      //创建一个有序Map,容量为时间区间,比如传入100,容量为101
      //用来容纳时间区间内的次数
      //---其实就是时间窗口
      this.window = new LinkedHashMap<>((int) timeUnitsInWindow + 1);
      this.timeUnitsInWindow = timeUnitsInWindow;
    }

    public void increment() {
      //记录一次调用
      long timeSlot = windowTimeUnit.convert(System.currentTimeMillis(), TimeUnit.MILLISECONDS);
      Long current = window.getOrDefault(timeSlot, 0L);
      window.put(timeSlot, ++current);
      //超出容量,删除最早那条
      //---维持窗口大小
      if (window.size() > timeUnitsInWindow) {
        Iterator<Long> iterator = window.keySet().iterator();
        if (iterator.hasNext()) {
          window.remove(iterator.next());
        }
      }
    }

    public long count() {
      //统计时间区间内调用次数  
      //---判定是否可以熔断
      long windowStartTime = windowTimeUnit.convert(System.currentTimeMillis() - windowTimeUnit.toMillis(timeUnitsInWindow), TimeUnit.MILLISECONDS);
      return window.entrySet().stream().filter(entry -> entry.getKey() >= windowStartTime).mapToLong(entry -> entry.getValue()).sum();
    }

    public void reset() {
      window.clear();
    }
  }

4.当断则断

  private synchronized void incrementFailures() {
    rollingFailures.increment();
    if (rollingFailures.count() >= options.getMaxFailures()) {
      if (state != CircuitBreakerState.OPEN) {
        open();
      } 
    }
  }

*LinkedHashMap简单理解为有顺序的HashMap,可以同时兼顾查值与按顺序删除操作,非常契合时间窗口的场景。

上一篇 下一篇

猜你喜欢

热点阅读