Eureka源码之Region、Zone、serviceUrls
一 getServiceUrlsMapFromConfig函数public static Map<String, List<String>> getServiceUrlsMapFromConfig(EurekaClientConfig clientConfig, String instanceZone, boolean preferSame
·
一 getServiceUrlsMapFromConfig函数
public static Map<String, List<String>> getServiceUrlsMapFromConfig(EurekaClientConfig clientConfig, String instanceZone, boolean preferSameZone) {
Map<String, List<String>> orderedUrls = new LinkedHashMap<>();
String region = getRegion(clientConfig);
String[] availZones = clientConfig.getAvailabilityZones(clientConfig.getRegion());
if (availZones == null || availZones.length == 0) {
availZones = new String[1];
availZones[0] = DEFAULT_ZONE;
}
logger.debug("The availability zone for the given region {} are {}", region, availZones);
int myZoneOffset = getZoneOffset(instanceZone, preferSameZone, availZones);
String zone = availZones[myZoneOffset];
List<String> serviceUrls = clientConfig.getEurekaServerServiceUrls(zone);
if (serviceUrls != null) {
orderedUrls.put(zone, serviceUrls);
}
int currentOffset = myZoneOffset == (availZones.length - 1) ? 0 : (myZoneOffset + 1);
while (currentOffset != myZoneOffset) {
zone = availZones[currentOffset];
serviceUrls = clientConfig.getEurekaServerServiceUrls(zone);
if (serviceUrls != null) {
orderedUrls.put(zone, serviceUrls);
}
if (currentOffset == (availZones.length - 1)) {
currentOffset = 0;
} else {
currentOffset++;
}
}
if (orderedUrls.size() < 1) {
throw new IllegalArgumentException("DiscoveryClient: invalid serviceUrl specified!");
}
return orderedUrls;
}
二 Region、Zone
上面这个函数,可以发现,客户端依次加载了两个内容,第一个是Region,第二个是Zone,从加载逻辑上我们可以判断他们之间的关系:
1 通过getRegion函数,可以从配置中读取一个Region,所以一个微服务应用只可以属于一个Region。如果不特别配置,默认是default。若我们要自己设置,可以通过eureka.client.region属性来定义。
public static String getRegion(EurekaClientConfig clientConfig) {
String region = clientConfig.getRegion();
if (region == null) {
region = DEFAULT_REGION;
}
region = region.trim().toLowerCase();
return region;
}
2 通过getAvailabilityZones函数,可以知道当我们没有特别为Region配置Zone时候,将默认采用defaultZone,这也是配置参数eureka.client.serviceUrl.defaultZone中defaultZone的由来。若要为应用指定Zone,可以通过eureka.client.availability-zones属性来进行设置。从该函数return返回值,可以知道Zone能够设置多个,并且通过逗号分隔配置。由此,我们可以判断Region与Zone是一个对多的关系。
public String[] getAvailabilityZones(String region) {
String value = this.availabilityZones.get(region);
if (value == null) {
value = DEFAULT_ZONE;
}
return value.split(",");
}
三 serviceUrls
在获取了Region和Zone的信息之后,才开始真正加载Eureka Sever的具体地址,它根据传入的参数根据一定算法确定加载位于哪一个Zone配置的serviceUrls
int myZoneOffset = getZoneOffset(instanceZone, preferSameZone, availZones);
String zone = availZones[myZoneOffset];
List<String> serviceUrls = clientConfig.getEurekaServerServiceUrls(zone);
下面查看getEurekaServerServiceUrls
public List<String> getEurekaServerServiceUrls(String myZone) {
String serviceUrls = this.serviceUrl.get(myZone);
if (serviceUrls == null || serviceUrls.isEmpty()) {
serviceUrls = this.serviceUrl.get(DEFAULT_ZONE);
}
if (!StringUtils.isEmpty(serviceUrls)) {
final String[] serviceUrlsSplit = StringUtils.commaDelimitedListToStringArray(serviceUrls);
List<String> eurekaServiceUrls = new ArrayList<>(serviceUrlsSplit.length);
for (String eurekaServiceUrl : serviceUrlsSplit) {
if (!endsWithSlash(eurekaServiceUrl)) {
eurekaServiceUrl += "/";
}
eurekaServiceUrls.add(eurekaServiceUrl);
}
return eurekaServiceUrls;
}
return new ArrayList<>();
}
当我们在微服务应用中使用Ribbon来实现服务调用时,对于Zone的设置在负载均衡时实现区域亲和性:Ribbon的默认策略会优先访问处于一个Zone中的服务端实例,只有当同一个Zone中没有可用服务端实例的时候才会访问其他Zone的实例。所以通过Zone属性的定义,配合实际部署物理结构,我们就可以有效设计出对区域性故障的容错集群。
更多推荐
已为社区贡献24条内容
所有评论(0)