负载均衡器之DynamicServerListLoadBalancer(三)

245 阅读1分钟

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

负载均衡器之DynamicServerListLoadBalancer

服务列表过滤

PollingServerListUpdater的start方法中

调用updateAction.doUpdate();

@VisibleForTesting
public void updateListOfServers() {
    List<T> servers = new ArrayList<T>();
    if (serverListImpl != null) {
        servers = serverListImpl.getUpdatedListOfServers();
        LOGGER.debug("List of Servers for {} obtained from Discovery client: {}",
                getIdentifier(), servers);

        if (filter != null) {
            servers = filter.getFilteredListOfServers(servers);
            LOGGER.debug("Filtered List of Servers for {} obtained from Discovery client: {}",
                    getIdentifier(), servers);
        }
    }
    updateAllServerList(servers);
}

getFilteredListOfServers方法主要用于对服务实例列表的过滤,通过传入服务实例清单,根据一些规则返回过滤后的服务实例清单。

AbstractServerListFilter:

public abstract class AbstractServerListFilter<T extends Server> implements ServerListFilter<T> {

    private volatile LoadBalancerStats stats;
    
    public void setLoadBalancerStats(LoadBalancerStats stats) {
        this.stats = stats;
    }
    
    public LoadBalancerStats getLoadBalancerStats() {
        return stats;
    }

}

定义过滤时需要的一个重要依据对象LoadBalancerStats

ZoneAffinityServerListFilter

@Override
public List<T> getFilteredListOfServers(List<T> servers) {
    if (zone != null && (zoneAffinity || zoneExclusive) && servers !=null && servers.size() > 0){
        List<T> filteredServers = Lists.newArrayList(Iterables.filter(
                servers, this.zoneAffinityPredicate.getServerOnlyPredicate()));
        if (shouldEnableZoneAffinity(filteredServers)) {
            return filteredServers;
        } else if (zoneAffinity) {
            overrideCounter.increment();
        }
    }
    return servers;
}

根据提供服务的实例所处区域与消费者自身所处区域进行比较,过滤掉不是同一处区域的实例。

DefaultNIWSServerListFilter:完全继承ZoneAffinityServerListFilter

ServerListSubsetFilter:继承ZoneAffinityServerListFilter,适用于拥有大规模服务器集群的系统

ZonePreferenceServerListFilter:Spring Cloud整合Eureka和Ribbon时默认使用的过滤器,它通过配置或Eureka实例元数据的所属区域来过滤同区域的服务实例。

import java.util.ArrayList;
import java.util.List;

import lombok.Data;
import lombok.EqualsAndHashCode;

import com.netflix.client.config.IClientConfig;
import com.netflix.config.ConfigurationManager;
import com.netflix.config.DeploymentContext.ContextKey;
import com.netflix.loadbalancer.Server;
import com.netflix.loadbalancer.ZoneAffinityServerListFilter;

/**
 * A filter that actively prefers the local zone (as defined by the deployment context, or
 * the Eureka instance metadata).
 *
 * @author Dave Syer
 */
@Data
@EqualsAndHashCode(callSuper = false)
public class ZonePreferenceServerListFilter extends ZoneAffinityServerListFilter<Server> {

   private String zone;

   @Override
   public void initWithNiwsConfig(IClientConfig niwsClientConfig) {
      super.initWithNiwsConfig(niwsClientConfig);
      if (ConfigurationManager.getDeploymentContext() != null) {
         this.zone = ConfigurationManager.getDeploymentContext().getValue(
               ContextKey.zone);
      }
   }

   @Override
   public List<Server> getFilteredListOfServers(List<Server> servers) {
      List<Server> output = super.getFilteredListOfServers(servers);
      if (this.zone != null && output.size() == servers.size()) {
         List<Server> local = new ArrayList<Server>();
         for (Server server : output) {
            if (this.zone.equalsIgnoreCase(server.getZone())) {
               local.add(server);
            }
         }
         if (!local.isEmpty()) {
            return local;
         }
      }
      return output;
   }

}