小知识,大挑战!本文正在参与「程序员必备小知识」创作活动
负载均衡器之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;
}
}