(如无特殊说明,本文中hostname特指eureka.instance.hostname,defaultZone特指eureka.client.serviceUrl.defaultZone)
先说一下我们采用的最终方案
spring:
application:
name: eureka
server:
port: 8761
eureka:
instance:
hostname: ${spring.cloud.client.ipAddress}
prefer-ip-address: true
client:
serviceUrl:
defaultZone: http://127.0.0.1:8762/eureka/,http://localhost:8763/eureka/
实际使用中,只要把defaultZone里的127.0.0.1 和 localhost换成相应的IP地址就可以。
打开Eureka监控http://127.0.0.1:8761/出现下图说明配置正确。
说几点原因:
1. 许多高可用的Eureka配置里都要设置hosts文件,它是必须的吗?
不是必须的,配置hosts文件的目的是使各个Eureka的eureka.instance.hostname不同。
Eureka互相注册要求各个Eureka实例的eureka.instance.hostname不同,如果相同,则会被Eureka标记为unavailable-replicas。我们最终把eureka.instance.hostname取了${spring.cloud.client.ipAddress}的值,这个值取的是当前启动Eureka的机器的IP,这样虽然配置一样但却自动区分了每台机器的Eureka,这时我们再取prefer-ip-address: true,就可以确保机器优先使用IP而不是到hosts解析域名。
2.prefer-ip-address是做什么用的?
直观来说,如果点击下面注册中心的可用实例列表中的地址,访问结果会分以下几个情况:
1)hostname和prefer-ip-address都没有配置,则访问 主机名:服务名:端口号,
如:http://desktop-1fkok7b:8761/info
2)配置了hostname而没有配置prefer-ip-address,则访问 hostname:服务名:端口号,
如:http://myhostname:8761/info
3) 一旦配置了prefer-ip-address,则访问 ipAddress:服务名:端口号,
如:http://172.20.10.3:8761/info
在最终方案里我们已经把hostname设置为当前机器IP(${spring.cloud.client.ipAddress}),可以想见prefer-ip-address并不是必须的,但是合理使用它可以避免因为访问主机名而请求不到服务的情况,当然或许还节约了地址解析的损耗(虽然比较小)。
3. 为什么把hostname设置为当前机器IP?
(这一段的前提是微服务规模在几十个以内)当然也可以设置为域名,但是你要配置hosts(如果配置到所有Docker镜像中显然庞大不够灵活),或者搭建内网DNS服务器(为高可用增加了一层负担),而随着统一配置中心的到来,或许直接使用IP倒是一个相当不错的选择。另外,如果你配置了hostname,那么其它服务注册到你的时候,其它服务的defaultZone要填写defaultZone: http://yourhostname:8761/eureka/ 以确保没有问题,但如果你的hostname配置的就是IP,那其它服务的defaultZone里直接填写IP就可以,如defaultZone:http://172.20.10.3:8761/eureka/ 。
4. 上面说的都是在不同机器上启动Eureka,能在同一台机器上启动多个Eureka吗?
当然可以,但是一定要保证各个Eureka的hostname不同,一种办法是常用的配置hosts文件,还有一种,是使用当前机器IP、127.0.0.1和localhost分别作为三个Eureka的hostname,事实证明也是可以的,在文末的Github的项目的no_hosts分支里有相应的实现。但是如果你使用127.0.0.1或localhost,注意一定要设置prefer-ip-address: false 。
5. 我在同一台机器上配置hosts,启动三个Eureka实例并设置prefer-ip-address: true,为什么显示unavailable-replicas?
一种原因是,你设置了prefer-ip-address: true,其它服务注册你时应该使用defaultZone:http://yourIP:8761/eureka/,图中使用的仍然是hostname名,导致错误发生。
另一种原因是,三个Eureka都设置了prefer-ip-address: true,导致最后解析出来的hostname都是相同的IP,使副本不可用。这也是4中为什么要设置prefer-ip-address: false的原因。
Git地址:https://github.com/wangfei0904306/eureka-HA