概述
defaultZone与serviceUrl的获取
我们平时都是用defaultZone,这个defaultZone到底是什么,为什么一定要用defaultZone,换个别的行不行。网上很多文章都是入门的,不会讲到这一点。
default-zone != defaultZone
我是用idea来写application.yml,里面对于属性的提示值不是采用骆驼命名法,而是使用短横线"-"隔开。
本来配置属性都有自动提示的,会发现defaultZone并不会提示,我天真的以为写成default-zone也可以,其实eureka并不认识这个。其它的属性使用短横线隔开和骆驼命名,是提前做了处理。而serviceUrl是真正的属性,service-url的配置内容是map,map的内容是可以自己发挥的,只要是key: value格式就行(注意有个空格)。有很多map类型的配置,比如availabilityZones,metadata-map都是的,内容虽然是key: value格式,但是都是可以自由发挥。其中metadata-map比较特殊,里面有个zone的属性,会被eureka client解析,当成客户端默认指向的zone来处理。(目前没有尝试出来效果)
其实写作default-zone的时候,eureka经过一系列的解析,最终认定,这个客户端没有配置有效的seviceUrls。。。然后自己加一个defaultZone,默认使用http://localhost:8761/eureka/作为地址,而我恰好也用8761作为地址,造成了很多误会。
源码解读:
我们来看service-url是如何获取的。
Eureka Client的属性都在EurekaClientConfig类接口中定义处理方法。
查看实现会有两个实现,我们用的是spring的,我们主要看getAvailabilityZones()和getEurekaServerServiceUrls()两个方法的实现。
// 根据region,从availabilityZones这个Map中获取key值对应的配置。
// availabilityZones是通过eureka.client.availability-zones配置的,
// 可以配置多个availabilityZones,key表示region,value表region对应的zones
// 假设有多个zones,用逗号隔开。
// region通过eureka.client.region来设置,假设不设置,默认为"us-east-1c"。
public String[] getAvailabilityZones(String region) {
String value = (String)this.availabilityZones.get(region);
if (value == null) {
value = "defaultZone";
}
return value.split(",");
}
// 根据zone来获取serviceUrls,假设用逗号隔开会拆分成数组。
public List<String> getEurekaServerServiceUrls(String myZone) {
String serviceUrls = (String)this.serviceUrl.get(myZone);
if (serviceUrls == null || serviceUrls.isEmpty()) {
serviceUrls = (String)this.serviceUrl.get("defaultZone");
}
if (!StringUtils.isEmpty(serviceUrls)) {
String[] serviceUrlsSplit = StringUtils.commaDelimitedListToStringArray(serviceUrls);
List<String> eurekaServiceUrls = new ArrayList(serviceUrlsSplit.length);
String[] var5 = serviceUrlsSplit;
int var6 = serviceUrlsSplit.length;
for(int var7 = 0; var7 < var6; ++var7) {
String eurekaServiceUrl = var5[var7];
if (!this.endsWithSlash(eurekaServiceUrl)) {
eurekaServiceUrl = eurekaServiceUrl + "/";
}
eurekaServiceUrls.add(eurekaServiceUrl.trim());
}
return eurekaServiceUrls;
} else {
return new ArrayList();
}
}
Eureka会先获取region,如果我们没有设置region,region默认值为"us-east-1c",然后会根据这个region去获取对应的availabilityZones。
然后循环availabilityZones的值,使用每个zone来调用getEurekaServerServiceUrls,获取serviceUrl,最终形成一个zone为key,serviceUrls(因为可能一个zone有多个serviceUrl)列表为value的map。
在使用serviceUrl的时候,使用两重循环:
会按照顺序,逐个取availabilityZones的zone,从map中获取serviceUrls,在逐个循环serviceUrls,来判断是否可达,如果任意serviceUrl可达则停止,否则一致尝试到最后。
如果availabilityZones为空,或者根据它的值取不到serviceUrls,则会返回key为defaultZone的serviceUrls。如果我们也指定了defaultZone对应的serviceUrls,会覆盖原来的defaultZone,否则使用默认的http:// localhost:8761/eureka。
那么问题来了,如果想用自己的zone,该如何设置。
首先要设置region,不设置也可以,不设置就按照"us-east-lc"来组织后面的设置。并且根据region一定要能获取availabilityZones的zone值,如果没有就会默认使用defaultZone。我们假设自己设置region为china。然后需要设值availabilityZones,假设有两个js:nj1,nj2。然后在serviceUrls中设置nj1: xxxx 换行nj2: xxxx,分别指向两个服务,我们故意设置nj2在前,nj1在后面,然后先放任这两个服务之间不互为peer。来试验一下效果。
坑:注意getAvailabilityZones这个方法不会trim(),所以逗号后面不要有空格,不然用带空格的key会找不到serviceUrl,这个实现实在有点掉价。而getEurekaServerServiceUrls方法是加了trim()方法的 ,逗号后面可以有空格。
eureka client配置
bootstrap.yml配置
spring:
application:
name: demo
cloud:
config:
#指向配置中心地址
uri: http://localhost:8888/
profile: dev
application.yml配置
server:
port: 8080
eureka:
instance:
hostname: localhost
client:
# 假设指定region为江苏
region: js
availability-zones:
#假设江苏下面有南京的两个region
js: nj2,nj1
service-url:
nj1: http://eureka-server1:8761/eureka
nj2: http://eureka-server2:8762/eureka
注意,我们把nj2设置在了availability-zones:的前面
模拟多台机器的eureka-server
我们准备了两个serverUrl,所以需要把server改成能启动两个的
先去hosts下添加hostName
127.0.0.1 eureka-server1
127.0.0.1 eureka-server2
准备两个yml
application-server1.yml
spring:
application:
name: eureka-server
server:
#指定服务端口
port: 8761
eureka:
#指定主机名称
instance:
hostname: eureka-server1
#server一定程度上也是client,互为client,
client:
#由于自己就是服务器,不需要注册到自己
register-with-eureka: false
#由于自己就是服务器,不需要从服务器获取注册信息
fetch-registry: false
#服务地址s
service-url:
defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/
application-server2.yml
spring:
application:
name: eureka-server
server:
#指定服务端口
port: 8762
eureka:
#指定主机名称
instance:
hostname: eureka-server2
#server一定程度上也是client,互为client,
client:
#由于自己就是服务器,不需要注册到自己
register-with-eureka: false
#由于自己就是服务器,不需要从服务器获取注册信息
fetch-registry: false
#服务地址
service-url:
defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/
准备两个启动项(可以在idea中复制)
分别指定Program arguments
指定为--spring.profiles.active=server1和--spring.profiles.active=server2
启动一下看看
因为前面设置availability-zones设置了nj2在前面,对应的是eureka-server2:8762的服务。我们设置availability-zones改为nj1在前面(nj1,nj2),然后需要重启两个eureka-server。会发现注册到了eureka-server1:8761下面了。
弄不明白的eureka.instance.metadata-map.zone
按照官网的说法,可以使用eureka.instance.metadata-map.zone来指定属于哪个zone的。我的理解是,假设配置了metadataMap.zone,那么会优先取这个zone对应的serviceUrls。其实并不是这样的。我查看源码也没看到跟metadataMap有关的地方。
将availability-zones改为nj1,nj2,设置eureka.instance.metadata-map.zone为nj2看看,同样三个服务都需要重启。
理想情况是服务注册到8762上,测试了一下,并不是这样的。仍然按照service-url来配置。说明我对官网那段话的理解是错的。
并且本身就有矛盾,client经过一系列的逻辑,最终会通过availabilityZones和serviceUrls结合来获取第一个能连接的Eureka Server,也就意味着期望以这个serviceUrl所属于的zone作为自身的zone。那修改metadataMap.zone还有什么意义呢。假设metadataMap.zone和serviceUrl所属的zone不同,难道所属一个zone,又故意从另一个zone中获取注册信息?从效率上讲肯定不合适。
等再往后看,看看能不能理解这个用处。
最后
以上就是调皮羊为你收集整理的Eureka--3、高可用注册中心的第一步,通过defaultZone深入理解zone和serviceUrldefaultZone与serviceUrl的获取default-zone != defaultZone源码解读:那么问题来了,如果想用自己的zone,该如何设置。弄不明白的eureka.instance.metadata-map.zone的全部内容,希望文章能够帮你解决Eureka--3、高可用注册中心的第一步,通过defaultZone深入理解zone和serviceUrldefaultZone与serviceUrl的获取default-zone != defaultZone源码解读:那么问题来了,如果想用自己的zone,该如何设置。弄不明白的eureka.instance.metadata-map.zone所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复