use of com.github.df.restypass.exception.execute.CircuitBreakException in project RestyPass by darren-fu.
the class RestyCommandExecutor method execute.
@Override
public Object execute(LoadBalancer lb, RestyCommand restyCommand) throws RestyException {
if (restyCommand.getRestyCommandConfig().isForceBreakEnabled()) {
throw new CircuitBreakException("circuit breaker is forced to open");
}
// 重试次数
int retry = restyCommand.getRestyCommandConfig().getRetry();
Object result = null;
CircuitBreaker circuitBreaker = CircuitBreakerFactory.createDefaultCircuitBreaker(restyCommand.getServiceName());
// RestyCommand ready to start
restyCommand.ready(circuitBreaker);
// 排除 彻底断路的server, 尝试过的server
// 1.判断command使用的serverInstanceList是否存在被熔断的server
// 1.1 存在的话 server加入 loadBalance 的excludeServerList
Set<String> excludeInstanceIdSet = circuitBreaker.getBrokenServer();
// 负载均衡器 选择可用服务实例
ServerInstance serverInstance = lb.choose(serverContext, restyCommand, excludeInstanceIdSet);
if (serverInstance == null) {
throw new RuntimeException("no instances found:" + restyCommand.getServiceName() + ":" + serverContext.getServerList(restyCommand.getServiceName()));
}
// 重试机制
for (int times = 0; times <= retry; times++) {
try {
boolean shouldPass = circuitBreaker.shouldPass(restyCommand, serverInstance);
if (!shouldPass) {
// fallback or exception
throw new CircuitBreakException("circuit breaker is open");
}
RestyFuture future = restyCommand.start(serverInstance);
RestyFuture futureArg = getFutureArg(restyCommand);
if (restyCommand.isAsyncArg()) {
// 直接返回null, 结果放入出参RestyFuture中
return null;
}
if (restyCommand.isAsyncReturn()) {
// 返回RestyFuture
return future;
}
// 同步调用
result = future.get();
if (restyCommand.getStatus() == RestyCommandStatus.FAILED) {
throw restyCommand.getFailException();
}
if (restyCommand.getStatus() == RestyCommandStatus.SUCCESS) {
// 响应成功,无需重试了
break;
}
} catch (Exception ex) {
if (times == retry) {
throw ex;
} else {
// 将本次使用的server 加入排除列表
if (excludeInstanceIdSet == null || excludeInstanceIdSet == Collections.EMPTY_SET) {
excludeInstanceIdSet = new HashSet<>();
}
if (serverInstance != null) {
excludeInstanceIdSet.add(serverInstance.getInstanceId());
}
// 选择server, 如果没有server可选则无需重试,直接抛出当前异常
serverInstance = lb.choose(serverContext, restyCommand, excludeInstanceIdSet);
if (serverInstance == null || excludeInstanceIdSet.contains(serverInstance.getInstanceId())) {
throw ex;
} else if (log.isDebugEnabled()) {
log.debug("请求切换服务实例重试:{}", serverInstance);
}
}
}
}
return result;
}
Aggregations