背景
服务部署亚洲区域和欧洲区域两个集群
自然希望亚洲区域消费者先调用亚洲区域集群,失败在调用欧洲区域集群eureka中出现zone概念,类似dubbo这里的调度策略
ZoneAwareClusterInvoker
- 存在首选的优先首选调用
- 调用同区域
- 无同区域且必须同区域调用则报错
- 负载均衡一次选择一个可用
- 所有提供者选择一个可用的
- 强行调用
public Result doInvoke(Invocation invocation, final List<Invoker<T>> invokers, LoadBalance loadbalance) throws RpcException {
// registry.preferred = true
存在首选配置 则直接调用
for (Invoker<T> invoker : invokers) {
ClusterInvoker<T> clusterInvoker = (ClusterInvoker<T>) invoker;
if (clusterInvoker.isAvailable() && clusterInvoker.getRegistryUrl()
.getParameter(REGISTRY_KEY + "." + PREFERRED_KEY, false)) {
return clusterInvoker.invoke(invocation);
}
}
获取当前所属区域 则直接调用同区域提供者
String zone = invocation.getAttachment(REGISTRY_ZONE);
if (StringUtils.isNotEmpty(zone)) {
for (Invoker<T> invoker : invokers) {
ClusterInvoker<T> clusterInvoker = (ClusterInvoker<T>) invoker;
if (clusterInvoker.isAvailable() && zone.equals(clusterInvoker.getRegistryUrl().getParameter(REGISTRY_KEY + "." + ZONE_KEY))) {
return clusterInvoker.invoke(invocation);
}
}
必须同区域调用 则直接报错
String force = invocation.getAttachment(REGISTRY_ZONE_FORCE);
if (StringUtils.isNotEmpty(force) && "true".equalsIgnoreCase(force)) {
throw new IllegalStateException("No registry instance in zone or no available providers in the registry, zone: "
+ zone
+ ", registries: " + invokers.stream().map(invoker -> ((MockClusterInvoker<T>) invoker).getRegistryUrl().toString()).collect(Collectors.joining(",")));
}
}
通过负载均选择调用
Invoker<T> balancedInvoker = select(loadbalance, invocation, invokers, null);
if (balancedInvoker.isAvailable()) {
return balancedInvoker.invoke(invocation);
}
负载均选择isAvailable不可用,则兜底选择可用的调用
for (Invoker<T> invoker : invokers) {
ClusterInvoker<T> clusterInvoker = (ClusterInvoker<T>) invoker;
if (clusterInvoker.isAvailable()) {
return clusterInvoker.invoke(invocation);
}
}
没有一个isAvailable可用,则兜底调用
return invokers.get(0).invoke(invocation);
}
思考
一般zone,我们期望同区域调用失败,在调用其他区域
String zone = invocation.getAttachment(REGISTRY_ZONE);
zone可否改成zone1,zone2,zone3
当zone1失败,降级zone2,而不是直接调用整个集群所有的提供者中可用的
从而更好地支持灾备与双活架构?