之前的实例都是单节点的eureka server系统,在实际的生产环境中,分布式系统采用springCloud,一般会采用多节点搭建高可用的系统架构,这样的话就不会因为单节点eureka server挂掉产生问题。
目录
一、架构图
这边暂时只以ribbon,eureka client和eureka server画的一个简单的网络拓扑图。
客户端访问通过nginx负载均衡,分发到不同的服务器,然后通过服务器eureka server调用ribbon,进行应用层的负载均衡,调用具体微服务service系统执行。(这个拓扑图比较简单,省略了网关,注册中心,还有存储相关内容),配置的双server系统,两个eureka server 互相注册,然后各微服务又注册进这两个注册中心,这样即使一个注册中心挂掉,整体服务也是可用的。
二、实现
1、配置eureka server
项目基于之前的项目基础上继续开发,之前项目:断路器聚合仪表盘实现
项目中用了两个注册中心,一个是之前的端口号12345,另一个是端口号12222的注册中心,服务用的是端口号为10002的微服务SPRING-CLIENT-01.
由于之前有一个eureka server,所以新的eureka server和之前创建方法一致。
需要注意的是两个server要互相注册,所以12345这个server配置文件里的eureka.client.service-url.defaultZone是12222的地址。
这边通过多个配置文件实现多个eureka server的配置。主要通过配置文件cusvar这个参数来激活对应的配置。
新建两个properties: application-server01.properties,application-server02.properties
application.properties内容更改为:
cusvar=cus3
#注册中心应用名称
spring.application.name= CONFIG-CENTER
#使用的配置文件名
spring.profiles.active= server02
application-server01.properties配置:
cusvar=server01
server.port = 12345
spring.application.name = CONFIG-CENTER
spring.cloud.config.server.git.uri = https://github.com/harrypitter/springCloudDemo.git
#eureka.instance.hostname:localhost
#eureka.client.service-url.defaultZone=http://${eureka.instance.hostname}:${server.port}/eureka/
#eureka.client.service-url.defaultZone=http://localhost:12345/eureka/
logging.level.com.netflix.eureka=OFF
logging.level.com.netflix.discovery=OFF
management.endpoints.web.exposure.include= '*'
management.endpoint.health.show-details= ALWAYS
eureka.instance.hostname= server1
eureka.instance.prefer-ip-address= false
# instance-id: ${spring.cloud.client.ipAddress}:${server.port}
#一定要设置为true或者不写,否则会出现unavailable-replicas
eureka.client.fetch-registry= true
#一定要设置为true或者不写,否则会出现unavailable-replicas
eureka.client.register-with-eureka= true
eureka.client.service-url.defaultZone=http://server2:12222/eureka/
,application-server02.properties配置:
cusvar=server02
server.port = 12222
spring.application.name = CONFIG-CENTER
spring.cloud.config.server.git.uri = https://github.com/harrypitter/springCloudDemo.git
#eureka.instance.hostname:localhost
#该应用为注册中心,不向自己注册自己
#eureka.client.register-with-eureka=false
#是否从euruka服务器获取注册信息
#eureka.client.fetch-registry=true
#eureka.client.service-url.defaultZone=http://${eureka.instance.hostname}:${server.port}/eureka/
#eureka.client.service-url.defaultZone=http://localhost:12222/eureka/
logging.level.com.netflix.eureka=OFF
logging.level.com.netflix.discovery=OFF
management.endpoints.web.exposure.include= '*'
management.endpoint.health.show-details= ALWAYS
eureka.instance.hostname= server2
eureka.instance.prefer-ip-address= false
# ip-address: 172.193.225.185
# instance-id: ${spring.cloud.client.ipAddress}:${server.port}
#一定要设置为true或者不写,否则会出现unavailable-replicas
eureka.client.fetch-registry= true
#一定要设置为true或者不写,否则会出现unavailable-replicas
eureka.client.register-with-eureka= true
eureka.client.service-url.defaultZone=http://server1:12345/eureka/
然后IDEA的Edit configuration 里面改为多实例支持。
特殊的一步,更改host文件 将server1,server2 对应ip地址修改,这里因为是本地,都改为127.0.0.1
然后更改appliction.properties 里面的 spring.profiles.active分别为sever01,sever02分别启动。
注意:两个sever是互相注册所以sever1的defaultZone是sever2地址,sever2的defaultZone是sever1地址
然后再浏览器中输入:localhost:12345
输入localhost:12222
这样就配置好了。
2、遇到的问题
我这边在配置中遇到了些问题,以下是总结的结论:
问题一:eureka.instance.hostname我单独使用的时候配置的时候都是使用localhost,你这里使用的是server1和server2,这样就需要去修改hosts文件太麻烦了,能不这么麻烦吗?
假如需要搭建eureka集群的话,那么eureka.instance.hostname不能重复,否则集群失败,所以不能为localhost或者ip地址。在测试中我刚开始使用的是localhost去进行集群发现无法成功。service-url.defaultZone写的地址记得使用如下格式:http://其他eurekaServer的hostname:其它eurekaServer的port/eureka/,多台集群这样的格式用逗号隔开。
问题二:你的eureka.instance.prefer-ip-address为false,这样就会导致我们看到的服务实例不显示ip,怎么办?
个人大概理解了下,prefer-ip-address: true为不使用主机名来定义注册中心的地址,而使用IP地址的形式,而defaultZone中是以域名的方式向注册中心注册的(测试了下使用IP注册到备份节点不可识别),最终导致分片节点不能识别匹配(IP地址与域名),而认为分片均处于不可达状态。
问题三:分布式注册中心出现在unavaliable-replicas上面
把eureka.instance.prefer-ip-address为false
把eureka.client.fetch-registry设置为true
把eureka.clinet.register-with-eureka设置为true
实际操作中还有一点要注意,就是两个注册中心的服务名字必须相同,不然注册的client服务只能发现配置第一个server。
3、配置eureka client
这边只需要在之前的client 的配置文件的defaultZone中加上第二个server的地址就可以了。
eureka.client.serviceUrl.defaultZone= http://server1:12345/eureka/,http://server2:12222/eureka/
然后启动两个server 和client。在浏览器中输入localhost:12345
浏览器中输入localhost:12222
这样就注册进来了。
实际过程中,由于sever1和sever2互相注册,所以只有有一个服务注册进其中一个sever,那么就会自动同步到另一个服务。
例如我这边你有一个服务SPRING-CLIENT-03,配置自注册进sever1:
server.port = 12000
eureka.client.serviceUrl.defaultZone= http://server1:12345/eureka/
spring.application.name= SPRING-CLIENT-03
spring.datasource.url=jdbc:mysql://127.0.0.1:3306/testmysql
spring.datasource.username=root
spring.datasource.password=123456
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
spring.datasource.max-idle=10
spring.datasource.max-wait=10000
spring.datasource.min-idle=5
spring.datasource.initial-size=5
management.endpoints.web.exposure.include= '*'
management.endpoint.health.show-details= ALWAYS
但是启动之后,查看localhost:12222也可以看到。
但如果sever1异常,而此时又重启了 SPRING-CLIENT-03,那么在留存的sever2里面是没有SPRING-CLIENT-03的,所以实际上还是尽量将服务注册进每个sever中。
以上代码github地址:源码地址