You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
789/BasicExample/CircuitBreaker.java

135 lines
4.9 KiB

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

/**
* 断路器模式实现
* 防止系统雪崩效应,保护系统稳定性
*/
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() + "]";
}
}