负载均衡器之ZoneAwareLoadBalancer

434 阅读1分钟

小知识,大挑战!本文正在参与「程序员必备小知识」创作活动

13负载均衡器之ZoneAwareLoadBalancer

ZoneAwareLoadBalancer负载均衡器是对DynamicServerListLoadBalancer的继承,DynamicServerListLoadBalancer没有重写选择具体服务实例的chooseServer方法,依然采用BaseLoadBalancer中实现的方法,使用RoundRobinRule规则,以线性轮询的方式来选择调用的服务实例。

ZoneAwareLoadBalancer重写了选择具体服务实例的chooseServer方法

@Override
public Server chooseServer(Object key) {
    if (!ENABLED.get() || getLoadBalancerStats().getAvailableZones().size() <= 1) {
        logger.debug("Zone aware logic disabled or there is only one zone");
        return super.chooseServer(key);
    }
    Server server = null;
    try {
        LoadBalancerStats lbStats = getLoadBalancerStats();
        Map<String, ZoneSnapshot> zoneSnapshot = ZoneAvoidanceRule.createSnapshot(lbStats);
        logger.debug("Zone snapshots: {}", zoneSnapshot);
        if (triggeringLoad == null) {
            triggeringLoad = DynamicPropertyFactory.getInstance().getDoubleProperty(
                    "ZoneAwareNIWSDiscoveryLoadBalancer." + this.getName() + ".triggeringLoadPerServerThreshold", 0.2d);
        }

        if (triggeringBlackoutPercentage == null) {
            triggeringBlackoutPercentage = DynamicPropertyFactory.getInstance().getDoubleProperty(
                    "ZoneAwareNIWSDiscoveryLoadBalancer." + this.getName() + ".avoidZoneWithBlackoutPercetage", 0.99999d);
        }
        Set<String> availableZones = ZoneAvoidanceRule.getAvailableZones(zoneSnapshot, triggeringLoad.get(), triggeringBlackoutPercentage.get());
        logger.debug("Available zones: {}", availableZones);
        if (availableZones != null &&  availableZones.size() < zoneSnapshot.keySet().size()) {
            String zone = ZoneAvoidanceRule.randomChooseZone(zoneSnapshot, availableZones);
            logger.debug("Zone chosen: {}", zone);
            if (zone != null) {
                BaseLoadBalancer zoneLoadBalancer = getLoadBalancer(zone);
                server = zoneLoadBalancer.chooseServer(key);
            }
        }
    } catch (Throwable e) {
        logger.error("Unexpected exception when choosing server using zone aware logic", e);
    }
    if (server != null) {
        return server;
    } else {
        logger.debug("Zone avoidance logic is not invoked.");
        return super.chooseServer(key);
    }
}
  1. 调用ZoneAvoidanceRule.createSnapshot,为当前负载均衡器中所有的Zone区域分别创建快照
  2. 调用ZoneAvoidanceRule.getAvailableZones(zoneSnapshot, triggeringLoad.get(), triggeringBlackoutPercentage.get());获取可用的的Zone区域集合
  3. 当获得可用Zone区域不为空,并且个数小于Zone区域总数,就随机选择一个Zone区域
  4. 在确定某个Zone区域后,获取对应Zone区域的负载均衡器,调用chooseServer方法来选择具体的服务实例,这里使用ZoneAvoidanceRule来挑选具体的服务实例。

这就是负载均衡器之ZoneAwareLoadBalancer的具体逻辑和实现,还有很多细节没有一一展开,以后的文章中我们再细说细聊。