dubbo源码分析第二十一篇一dubbo集群容错策略-ZoneAwareCluster区域调用

背景

服务部署亚洲区域和欧洲区域两个集群
自然希望亚洲区域消费者先调用亚洲区域集群,失败在调用欧洲区域集群

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,而不是直接调用整个集群所有的提供者中可用的

从而更好地支持灾备与双活架构?

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值