本文将深入解析Dubbo 2.7的集群容错机制,详细剖析6种策略的实现原理与适用场景,帮助开发者根据业务需求选择最佳容错方案。
Dubbo 2.7 集群容错策略源码解析
学习目标
完成本章后,你可以:
掌握6种集群容错策略的核心区别与应用场景
分析FailoverClusterInvoker的重试机制与Provider切换逻辑
理解Failback策略的异步定时重试实现原理
比较Forking并行调用与Broadcast遍历调用的资源消耗差异
1. Cluster扩展体系
/**
* Cluster —— 集群容错策略的SPI扩展点
*
* @SPI(FailoverCluster.NAME)
* public interface Cluster {
* Invoker join(Directory directory) throws RpcException;
* }
*
* 每个Cluster实现负责将Directory转换为一个特定容错的Invoker包装
*
* 实现关系:
* Cluster.join(directory)
* → FailoverCluster(默认) → FailoverClusterInvoker
* → FailfastCluster → FailfastClusterInvoker
* → FailsafeCluster → FailsafeClusterInvoker
* → FailbackCluster → FailbackClusterInvoker
* → ForkingCluster → ForkingClusterInvoker
* → BroadcastCluster → BroadcastClusterInvoker
* → AvailableCluster → AvailableClusterInvoker
* → MergeableCluster → MergeableClusterInvoker
*/
2. FailoverClusterInvoker——默认策略
/**
* FailoverClusterInvoker —— 失败自动切换(默认策略)
*
* 算法:
* ① 通过Directory获取可用Provider列表
* ② 通过LoadBalance选择一个执行
* ③ 如果失败(含超时),从列表中移除该Provider
* ④ 重新LoadBalance选择 → 执行
* ⑤ 最多重试 retries 次
*
* 重要约束:必须用于幂等操作!
*/
class FailoverClusterInvokerSimulation extends AbstractClusterInvoker {
@Override
public Result doInvoke(Invocation invocation,
List invokers,
LoadBalance loadbalance) throws RpcException {
// ===== 1. 参数准备 =====
String methodName = invocation.getMethodName();
int retries = getUrl().getMethodParameter(
methodName, Constants.RETRIES_KEY, 2); // 默认重试次数=2
if (invokers.size() == 1) {
retries = 0; // 只有一个Provider不重试
}
// ===== 2. 保存原始Invoker列表 =====
List invoked = new ArrayList(invokers.size());
// ===== 3. 主轮询 =====
RpcException lastException = null;
for (int i = 0; i !inv.equals(invoker))
.collect(Collectors.toList());
} catch (Throwable t) {
lastException = new RpcException(
"Failover invoke error", t);
}
}
// ===== 4. 超出重试次数 → 抛出最终的异常 =====
throw new RpcException(
"Failed to invoke after " + retries + " retries, " +
"last error: " + lastException.getMessage(), lastException);
}
}
3. 其他五种策略快速对比
/**
* 六种集群容错策略的源码对比
*/
class AllClusterStrategies