spring cloud配置高可用eureka时遇到的一些坑
考虑到注册中心的高可用,今天搭建一下eureka集群,并在中途遇到一些小的坑,前前后后花了两个小时来排除,在这里记录一下,以供后面查看。
首先,贴上要达到的效果:
一、起两个eureka模拟集群,在ds replicas中显示集群中的其他成员。
二、在注册服务列表中正确显示我们注册了两个注册中心。
三、available-replicas中正确显示集群中的其他注册中心。
1、用ip而非主机名配置注册服务。
最开始,我并不想使用主机名来注册服务中心,我想直接使用ip,然后在服务的status一栏显示ip和端口信息,而不是显示电脑用户名。这一栏的显示由参数eureka.instance.instance-id控制。我按照之前的做法将这个属性设置为
${spring.cloud.client.ipaddress}:${server.port}
但在启动服务后发现status中描述变成了“${spring.cloud.client.ipaddress}:8762”,${spring.cloud.client.ipaddress}属性并没有读取到,经过查阅发现在finchley版本中,这个变量改名为了spring.cloud.client.ip-address。配置之后,成功显示了ip:port的形式。
但在后续的配置中,无论如何配置其他选项,上面提到要达到的目标中的第一点和第三点都无法正常完成,所以只能放弃用ip配置的想法,后续有时间仔细学习源码的时候再来看这一点吧。就修改hosts将ip映射为主机名eureka1和eureka2。
2、第二个发生的问题是,available-replicas不正常显示。(已经是采用的服务主机名的形式注册了,非ip形式)
这个问题出在eureka.instance.appname这个参数,集群每个副本的这个属性必须一样。我在网上看到有的文章讲的是application配置文件中的spring.application.name属性要一样,这个说法应该是不完全正确的。当用户未配置appname时,spring cloud会优先使用spring.application.name来覆盖此值,所以造成了这个误解。
后面我也做了实验,当两个副本spring.application.name不同,但appname相同时,也会被识别为可用的并正常显示。此种情况下eureka也会将这两个不同spring.application.name的服务识别为同一个服务的不同副本,而不会根据spring.application.name将其视为不同服务。
接下来的这一点,也是available-replicas正常显示的条件之一。
3、为实现高可用,注册中心必须注册自己。
即eureka.client.registerwitheureka和eureka.client.fetchregistry两个属性,不能设置为false。这两个属性默认为true,只要不手动设置为false,服务就会想注册中心注册自己。
所有的服务注册时,eureka.client.serviceurl.defaultzone必须指向所有的注册中心,不然部署高可用的中心就没有意义了。当注册中心注册自己的时候,这个属性可以不包含自身的地址。
另外需要注意的是,第一个注册中心启动的时候,会抛出一个错误:
com.netflix.discovery.shared.transport.transportexception: cannot execute request on any known server
这是因为它在试图向指定的注册中心注册自己的时候,目标中心还没有启动。这个错误无伤大雅,因为eureka的注册是有心跳的,等目标中心启动之后,这个服务会在下一次心跳的时候自动注册进去。