use of com.github.df.restypass.enums.CircuitBreakerStatus in project RestyPass by darren-fu.
the class DefaultCircuitBreaker method shouldPass.
@Override
public boolean shouldPass(RestyCommand restyCommand, ServerInstance serverInstance) {
// 未启动
if (!started) {
return true;
}
String metricsKey = getMetricsKey(restyCommand.getPath(), serverInstance.getInstanceId());
// 强制短路
CircuitBreakerStatus cbStatus = statusMap.get(metricsKey);
if (restyCommand.getRestyCommandConfig().isForceBreakEnabled()) {
statusMap.put(metricsKey, CircuitBreakerStatus.FORCE_BREAK);
return false;
} else if (CircuitBreakerStatus.FORCE_BREAK == cbStatus) {
// 强制短路关闭后,OPEN
statusMap.put(metricsKey, CircuitBreakerStatus.OPEN);
}
// 断路器未启用
if (!restyCommand.getRestyCommandConfig().isCircuitBreakEnabled()) {
return true;
}
// 获取统计段
Metrics metrics = getCommandMetrics(metricsKey);
if (metrics == null) {
return true;
}
// 半开状态说明已经有请求通过断路器,尝试恢复短路,所以其它请求直接拒绝,继续熔断
if (CircuitBreakerStatus.HALF_OPEN == cbStatus) {
return false;
}
// 是否应该通过
boolean shouldPass = true;
// 获取计数器
Metrics.SegmentMetrics segmentMetrics = metrics.getMetrics();
// 计数器中失败数量和比例超过阀值,则触发短路判断
if (// 连续失败次数达到阀值
segmentMetrics.getContinuousFailCount() >= continuousFailCount || // 失败比例以及失败数量达到阀值
(segmentMetrics.failCount() >= breakFailCount && segmentMetrics.failPercentage() >= breakFailPercentage)) {
CircuitBreakerStatus breakerStatus = cbStatus;
shouldPass = false;
if (breakerStatus == null || breakerStatus == CircuitBreakerStatus.OPEN) {
// 短路
statusMap.put(metricsKey, CircuitBreakerStatus.BREAK);
} else if (breakerStatus == CircuitBreakerStatus.HALF_OPEN) {
// noop
} else {
// 如果上次的请求距离现在超过阀值,则允许一次试探请求
long now = System.currentTimeMillis();
if (segmentMetrics.last() != null && (now - segmentMetrics.last() > halfOpenMilliseconds)) {
final ReentrantLock lock = getHalfOpenLockInMap(metricsKey);
lock.lock();
try {
// 判断当前短路状态 确保只有一个请求通过
if (statusMap.get(metricsKey) == CircuitBreakerStatus.BREAK) {
statusMap.put(metricsKey, CircuitBreakerStatus.HALF_OPEN);
shouldPass = true;
}
} finally {
lock.unlock();
}
}
}
if (log.isDebugEnabled()) {
if (shouldPass) {
log.debug("尝试恢复短路服务:{}:{},metrics:{}", restyCommand.getServiceName(), restyCommand.getPath(), metrics);
} else {
log.debug("熔断服务:{}:{},metrics:{}", restyCommand.getServiceName(), restyCommand.getPath(), metrics);
}
}
}
return shouldPass;
}
use of com.github.df.restypass.enums.CircuitBreakerStatus in project RestyPass by darren-fu.
the class DefaultCircuitBreaker method startTask.
/**
* 消费队列 统计已完成的command信息,更新 segment
*/
private void startTask() {
Executors.newSingleThreadExecutor().submit(() -> {
log.info("启动RestyCommand统计线程:" + this.eventKey);
while (true) {
try {
// 阻塞
RestyCommand firstCommand = commandQueue.take();
// 取出queue中所有的数据
List<RestyCommand> commandList = new LinkedList<>();
commandList.add(firstCommand);
commandQueue.drainTo(commandList);
for (RestyCommand restyCommand : commandList) {
String key = getMetricsKey(restyCommand.getPath(), restyCommand.getInstanceId());
// 获取 计数器
Metrics metrics = getCommandMetrics(key);
if (metrics == null) {
log.warn("获取计数器失败:{}", key);
continue;
}
boolean isSuccess = isCommandSuccessExecuted(restyCommand);
boolean forceUseNewMetrics = false;
// 如果当前处在短路或半短路状态
CircuitBreakerStatus breakerStatus = statusMap.get(key);
if ((breakerStatus == CircuitBreakerStatus.BREAK || breakerStatus == CircuitBreakerStatus.HALF_OPEN)) {
// 结果成功 则不再短路,打开断路器
if (isSuccess) {
// 并使用一个新的计数器
forceUseNewMetrics = true;
statusMap.put(key, CircuitBreakerStatus.OPEN);
} else {
// 否则恢复到短路状态
statusMap.put(key, CircuitBreakerStatus.BREAK);
}
}
metrics.store(isSuccess, forceUseNewMetrics);
}
if (log.isTraceEnabled()) {
log.trace("处理完成, 处理个数:{},剩余:{}个", commandList.size(), commandQueue.size());
}
} catch (Exception ex) {
log.error("断路器RestyCommand处理失败:{}", ex);
}
}
});
}
Aggregations