聊聊eureka的ZoneAffinityServerListFilter
序
本文主要研究一下eureka的ZoneAffinityServerListFilter
ZoneAffinityServerListFilter
ribbon-loadbalancer-2.2.5-sources.jar!/com/netflix/loadbalancer/ZoneAffinityServerListFilter.java
/**
* This server list filter deals with filtering out servers based on the Zone affinity.
* This filtering will be turned on if either {@link CommonClientConfigKey#EnableZoneAffinity}
* or {@link CommonClientConfigKey#EnableZoneExclusivity} is set to true in {@link IClientConfig} object
* passed into this class during initialization. When turned on, servers outside the same zone (as
* indicated by {@link Server#getZone()}) will be filtered out. By default, zone affinity
* and exclusivity are turned off and nothing is filtered out.
*
* @author stonse
*
*/
public class ZoneAffinityServerListFilter<T extends Server> extends
AbstractServerListFilter<T> implements IClientConfigAware {
//......
@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;
}
}
可以看到這裡首先呼叫了zoneAffinityPredicate.getServerOnlyPredicate()進行過濾;然後再呼叫shouldEnableZoneAffinity判斷是否真的需要返回過濾後的資料。
ZoneAffinityPredicate
ribbon-loadbalancer-2.2.5-sources.jar!/com/netflix/loadbalancer/ZoneAffinityPredicate.java
/**
* A predicate the filters out servers that are not in the same zone as the client's current
* zone. The current zone is determined from the call
*
* <pre>{@code
* ConfigurationManager.getDeploymentContext().getValue(ContextKey.zone);
* }</pre>
*
* @author awang
*
*/
public class ZoneAffinityPredicate extends AbstractServerPredicate {
private final String zone = ConfigurationManager.getDeploymentContext().getValue(ContextKey.zone);
public ZoneAffinityPredicate() {
}
@Override
public boolean apply(PredicateKey input) {
Server s = input.getServer();
String az = s.getZone();
if (az != null && zone != null && az.toLowerCase().equals(zone.toLowerCase())) {
return true;
} else {
return false;
}
}
}
可以看到這裡對server的zone進行判斷,相同的zone才選取出來。
shouldEnableZoneAffinity
private boolean shouldEnableZoneAffinity(List<T> filtered) {
if (!zoneAffinity && !zoneExclusive) {
return false;
}
if (zoneExclusive) {
return true;
}
LoadBalancerStats stats = getLoadBalancerStats();
if (stats == null) {
return zoneAffinity;
} else {
logger.debug("Determining if zone affinity should be enabled with given server list: {}", filtered);
ZoneSnapshot snapshot = stats.getZoneSnapshot(filtered);
double loadPerServer = snapshot.getLoadPerServer();
int instanceCount = snapshot.getInstanceCount();
int circuitBreakerTrippedCount = snapshot.getCircuitTrippedCount();
if (((double) circuitBreakerTrippedCount) / instanceCount >= blackOutServerPercentageThreshold.get()
|| loadPerServer >= activeReqeustsPerServerThreshold.get()
|| (instanceCount - circuitBreakerTrippedCount) < availableServersThreshold.get()) {
logger.debug("zoneAffinity is overriden. blackOutServerPercentage: {}, activeReqeustsPerServer: {}, availableServers: {}",
new Object[] {(double) circuitBreakerTrippedCount / instanceCount, loadPerServer, instanceCount - circuitBreakerTrippedCount});
return false;
} else {
return true;
}
}
}
這裡進行判斷,如果目標zone的server統計資料不是太好,達到斷路的標準,則不會返回該zone的server。
ZonePreferenceServerListFilter
spring-cloud-netflix-ribbon-2.0.0.RC1-sources.jar!/org/springframework/cloud/netflix/ribbon/ZonePreferenceServerListFilter.java
/**
* A filter that actively prefers the local zone (as defined by the deployment context, or
* the Eureka instance metadata).
*
* @author Dave Syer
*/
public class ZonePreferenceServerListFilter extends ZoneAffinityServerListFilter<Server> {
//......
@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<>();
for (Server server : output) {
if (this.zone.equalsIgnoreCase(server.getZone())) {
local.add(server);
}
}
if (!local.isEmpty()) {
return local;
}
}
return output;
}
}
Spring Cloud的ZonePreferenceServerListFilter繼承了eureka的ZoneAffinityServerListFilter,重寫了getFilteredListOfServers方法,即eureka的ZoneAffinityServerListFilter計算出來沒有根據zone過濾的話,那麼它會再過濾一次,選出跟例項相同zone的server。注意這裡進行了判斷,如根據zone過濾出來為空,則返回父類過濾出來server,即不再根據zone進行過濾。
小結
eureka提供了ZoneAffinityServerListFilter,可以對server進行zone親和性過濾,同時還會根據server的健康統計判斷是否需要使用進行zone親和過濾後的server,如果不應該開啟,則返回沒有過濾的server列表。比如沒有跟該例項相同zone的server列表,那麼很明顯就是不應該返回根據zone進行過濾後的空列表。
doc
相關文章
- 聊聊如何基於eureka後設資料擴充套件namespace功能套件namespace
- Eureka 原始碼分析之 Eureka Server原始碼Server
- Eureka詳解系列(三)--探索Eureka強大的配置體系
- Eureka詳解系列(四)--Eureka Client部分的原始碼和配置client原始碼
- Eureka詳解系列(五)--Eureka Server部分的原始碼和配置Server原始碼
- Eureka與Zookeeper的區別
- Eureka原理剖析
- Eureka 基本教程
- 搭建Eureka Clientclient
- 服務註冊與發現【Eureka】- Eureka簡介
- Eureka的微服務之間呼叫微服務
- Eureka實現微服務的呼叫微服務
- SpringCloud之EurekaSpringGCCloud
- SpringCloud (一) EurekaSpringGCCloud
- Eureka使用總結
- Eureka原始碼分析原始碼
- 深入理解Eureka
- Eureka註冊中心
- 初識Spring Cloud Eureka(三)(Eureka客戶端之間 服務的相互呼叫)SpringCloud客戶端
- Eureka詳解系列(二)--如何使用Eureka(原生API,無Spring)APISpring
- Eureka-實現微服務的呼叫微服務
- EureKa與ZooKeeper的CAP原則分析
- 超詳細的Eureka原始碼解析原始碼
- 聊聊canal的BooleanMutexBooleanMutex
- 聊聊elasticsearch的ElectMasterServiceElasticsearch
- 聊聊elasticsearch的LagDetectorElasticsearch
- 聊聊elasticsearch的NodesFaultDetectionElasticsearch
- 聊聊elasticsearch的MasterFaultDetectionElasticsearch
- 聊聊機器學習的套路機器學習
- 聊聊JS裡的thisJS
- 聊聊arthas的ArthasBootstrapboot
- 聊聊arthas的HttpTermServerHTTPServer
- Eureka學習記錄
- 4、Spring Cloud EurekaSpringCloud
- 【Spring Cloud】之 EurekaSpringCloud
- eureka實現服務之間的呼叫
- SpringCloud包含的微服務介紹--EurekaSpringGCCloud微服務
- 聊聊canal的CanalAdapterServiceAPT