一、限流器
public class RateLimiter {
private static final int WINDOW_LIMIT = 100;
private static long WINDOW_START_TIME = System.currentTimeMillis();
private static final long WINDOW_DURATION = 60 * 1000;
private static final AtomicInteger WINDOW_ACC_CNT = new AtomicInteger(0);
public boolean tryAcquire() {
long now = System.currentTimeMillis();
if (now - WINDOW_START_TIME >= WINDOW_DURATION) {
WINDOW_START_TIME = now;
WINDOW_ACC_CNT.set(0);
}
return WINDOW_ACC_CNT.incrementAndGet() <= WINDOW_LIMIT;
}
public void acquire(){
for(;;){
try {
if (tryAcquire()){
break;
}
TimeUnit.MICROSECONDS.sleep(500);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
}
}
二、熔断器
public class CircuitBreaker {
/**
* 失败窗口统计开始时间
*/
private Long failWindowStartTime = System.currentTimeMillis();
/**
* 失败窗口,默认60s
*/
private Long failWindowDuration = 60000L;
/**
* 窗口内累积失败次数,默认100次
*/
private AtomicInteger failWindowAccFailCount = new AtomicInteger(0);
/**
* 窗口内最大失败次数
*/
private Long failWindowMaxCount = 5L;
/**
* 熔断器开始时间
*/
private Long breakerStartTime;
/**
* 熔断两分钟
*/
private Long breakerDuration = 2 * 60000L;
/**
* 熔断器状态
*/
private State state = State.CLOSED;
public static CircuitBreaker create(MiddlewareConfigProperties.LimitMiddlewareConfig limitConfig) {
CircuitBreaker circuitBreaker = new CircuitBreaker();
if (limitConfig == null){
return circuitBreaker;
}
if (limitConfig.getFailWindowDuration() != null) {
circuitBreaker.setFailWindowDuration(limitConfig.getFailWindowDuration());
}
if (limitConfig.getFailWindowMaxCount() != null) {
circuitBreaker.setFailWindowMaxCount(limitConfig.getFailWindowMaxCount());
}
if (limitConfig.getBreakerDuration() != null) {
circuitBreaker.setBreakerDuration(limitConfig.getBreakerDuration());
}
return circuitBreaker;
}
public enum State {
CLOSED,
OPEN
}
public void onSuccess() {
// reset
reset();
}
public void reset() {
state = State.CLOSED;
failWindowStartTime = System.currentTimeMillis();
failWindowAccFailCount.set(0);
}
public void onFail() {
long duration = System.currentTimeMillis() - failWindowStartTime;
if (duration >= failWindowDuration) { // 如果已超过窗口时间,重置
reset();
}
// 判断失败次数
int failCnt = failWindowAccFailCount.incrementAndGet();
if (failCnt >= failWindowMaxCount) { // 打开熔断器
state = State.OPEN;
breakerStartTime = System.currentTimeMillis();
}
}
public State getBreakerState() {
if (state == State.CLOSED) {
return State.CLOSED;
}
// 判断是否已经超过熔断时间
long breakDuration = System.currentTimeMillis() - breakerStartTime;
if (breakDuration > breakerDuration) { // 已经熔断2分钟,关闭熔断器
reset();
return State.CLOSED;
}
return State.OPEN;
}
}