|
|
/**
|
|
|
* 断路器模式实现
|
|
|
* 防止系统雪崩效应,保护系统稳定性
|
|
|
*/
|
|
|
import java.util.concurrent.atomic.AtomicInteger;
|
|
|
import java.util.concurrent.atomic.AtomicLong;
|
|
|
|
|
|
public class CircuitBreaker {
|
|
|
// 断路器状态枚举
|
|
|
public enum State {
|
|
|
CLOSED, // 关闭状态,允许请求通过
|
|
|
OPEN, // 开路状态,拒绝请求
|
|
|
HALF_OPEN // 半开状态,允许有限请求通过以检测服务是否恢复
|
|
|
}
|
|
|
|
|
|
private final String name; // 断路器名称
|
|
|
private final int failureThreshold; // 失败阈值
|
|
|
private final long resetTimeoutMs; // 重置超时时间(毫秒)
|
|
|
private final int successThreshold; // 半开状态下的成功阈值
|
|
|
|
|
|
private volatile State state = State.CLOSED; // 当前状态
|
|
|
private final AtomicInteger failureCount = new AtomicInteger(0); // 失败计数
|
|
|
private final AtomicInteger successCount = new AtomicInteger(0); // 成功计数
|
|
|
private final AtomicLong lastFailureTime = new AtomicLong(0); // 最后一次失败时间
|
|
|
|
|
|
// 默认构造函数
|
|
|
public CircuitBreaker(String name) {
|
|
|
this(name, 5, 30000, 2); // 默认5次失败后开路,30秒后尝试半开,2次成功后关闭
|
|
|
}
|
|
|
|
|
|
// 自定义参数构造函数
|
|
|
public CircuitBreaker(String name, int failureThreshold, long resetTimeoutMs, int successThreshold) {
|
|
|
this.name = name;
|
|
|
this.failureThreshold = failureThreshold;
|
|
|
this.resetTimeoutMs = resetTimeoutMs;
|
|
|
this.successThreshold = successThreshold;
|
|
|
System.out.println("断路器初始化: " + name +
|
|
|
", 失败阈值: " + failureThreshold +
|
|
|
", 重置时间: " + resetTimeoutMs + "ms");
|
|
|
}
|
|
|
|
|
|
// 尝试执行请求
|
|
|
public boolean allowRequest() {
|
|
|
switch (state) {
|
|
|
case CLOSED:
|
|
|
// 关闭状态,允许请求通过
|
|
|
return true;
|
|
|
case OPEN:
|
|
|
// 开路状态,检查是否可以进入半开状态
|
|
|
if (System.currentTimeMillis() - lastFailureTime.get() > resetTimeoutMs) {
|
|
|
// 超时,切换到半开状态
|
|
|
state = State.HALF_OPEN;
|
|
|
System.out.println("断路器状态切换: " + name + " 从 OPEN 到 HALF_OPEN");
|
|
|
return true;
|
|
|
}
|
|
|
return false;
|
|
|
case HALF_OPEN:
|
|
|
// 半开状态,允许请求通过
|
|
|
return true;
|
|
|
default:
|
|
|
return false;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
// 记录请求成功
|
|
|
public void recordSuccess() {
|
|
|
switch (state) {
|
|
|
case CLOSED:
|
|
|
// 关闭状态,重置失败计数
|
|
|
failureCount.set(0);
|
|
|
break;
|
|
|
case HALF_OPEN:
|
|
|
// 半开状态,增加成功计数
|
|
|
int currentSuccess = successCount.incrementAndGet();
|
|
|
if (currentSuccess >= successThreshold) {
|
|
|
// 达到成功阈值,切换到关闭状态
|
|
|
reset();
|
|
|
System.out.println("断路器状态切换: " + name + " 从 HALF_OPEN 到 CLOSED");
|
|
|
}
|
|
|
break;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
// 记录请求失败
|
|
|
public void recordFailure() {
|
|
|
switch (state) {
|
|
|
case CLOSED:
|
|
|
// 关闭状态,增加失败计数
|
|
|
int currentFailure = failureCount.incrementAndGet();
|
|
|
if (currentFailure >= failureThreshold) {
|
|
|
// 达到失败阈值,切换到开路状态
|
|
|
state = State.OPEN;
|
|
|
lastFailureTime.set(System.currentTimeMillis());
|
|
|
System.out.println("断路器状态切换: " + name + " 从 CLOSED 到 OPEN");
|
|
|
}
|
|
|
break;
|
|
|
case HALF_OPEN:
|
|
|
// 半开状态下失败,立即切换到开路状态
|
|
|
state = State.OPEN;
|
|
|
lastFailureTime.set(System.currentTimeMillis());
|
|
|
successCount.set(0);
|
|
|
System.out.println("断路器状态切换: " + name + " 从 HALF_OPEN 到 OPEN");
|
|
|
break;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
// 重置断路器
|
|
|
public void reset() {
|
|
|
state = State.CLOSED;
|
|
|
failureCount.set(0);
|
|
|
successCount.set(0);
|
|
|
lastFailureTime.set(0);
|
|
|
System.out.println("断路器重置: " + name);
|
|
|
}
|
|
|
|
|
|
// 获取当前状态
|
|
|
public State getState() {
|
|
|
return state;
|
|
|
}
|
|
|
|
|
|
// 获取名称
|
|
|
public String getName() {
|
|
|
return name;
|
|
|
}
|
|
|
|
|
|
// 获取失败计数
|
|
|
public int getFailureCount() {
|
|
|
return failureCount.get();
|
|
|
}
|
|
|
|
|
|
@Override
|
|
|
public String toString() {
|
|
|
return "CircuitBreaker[name=" + name + ", state=" + state + ", failures=" + failureCount.get() + "]";
|
|
|
}
|
|
|
} |