先抛一个问题给我聪明的读者,如果你们使用微服务SpringCloud-Netflix进行业务开发,那么线上注册中心肯定也是用了集群部署,问题来了:
你了解Eureka注册中心集群如何实现客户端请求负载及故障转移吗?
可以先思考一分钟,我希望你能够带着问题来阅读此篇文章,也希望你看完文章后会有所收获!
背景前段时间线上Sentry平台报警,多个业务服务在和注册中心交互时,例如续约和注册表增量拉取等都报了Request execution failed with message : Connection refused 的警告:
紧接着又看到 Request execution succeeded on retry #2 的日志。
看到这里,表明我们的服务在尝试两次重连后和注册中心交互正常了。
一切都显得那么有惊无险,这里报Connection refused 是注册中心网络抖动导致的,接着触发了我们服务的重连,重连成功后一切又恢复正常。
这次的报警虽然没有对我们线上业务造成影响,并且也在第一时间恢复了正常,但作为一个爱思考的小火鸡,我很好奇这背后的一系列逻辑:Eureka注册中心集群如何实现客户端请求负载及故障转移?
注册中心集群负载测试线上注册中心是由三台机器组成的集群,都是4c8g的配置,业务端配置注册中心地址如下(这里的peer来代替具体的ip地址):
eureka.client.serviceUrl.defaultZone=http://peer1:8080/eureka/,:8080/eureka/,:8080/eureka/我们可以写了一个Demo进行测试:
注册中心集群负载测试1、本地通过修改EurekaServer服务的端口号来模拟注册中心集群部署,分别以8761和8762两个端口进行启动
2、启动客户端SeviceA,配置注册中心地址为::8761/eureka,:8762/eureka
3、启动SeviceA时在发送注册请求的地方打断点:AbstractJerseyEurekaHttpClient.register(),如下图所示:
这里看到请求注册中心时,连接的是8761这个端口的服务。
4、更改ServiceA中注册中心的配置::8762/eureka,:8761/eureka
5、重新启动SeviceA然后查看端口,如下图所示:
此时看到请求注册中心是,连接的是8762这个端口的服务。 注册中心故障转移测试
以两个端口分别启动EurekaServer服务,再启动一个客户端ServiceA。启动成功后,关闭一个8761端口对应的服务,查看此时客户端是否会自动迁移请求到8762端口对应的服务:
1、以8761和8762两个端口号启动EurekaServer
2、启动ServiceA,配置注册中心地址为::8761/eureka,:8762/eureka
3、启动成功后,关闭8761端口的EurekaServer
4、在EurekaClient端发送心跳请求的地方打上断点:AbstractJerseyEurekaHttpClient.sendHeartBeat()
5、查看断点处数据,第一次请求的EurekaServer是8761端口的服务,因为该服务已经关闭,所以返回的response是null
6、第二次会重新请求8762端口的服务,返回的response为状态为200,故障转移成功,如下图:
思考
通过这两个测试Demo,我以为EurekaClient每次都会取defaultZone配置的第一个host作为请求EurekaServer的请求的地址,如果该节点故障时,会自动切换配置中的下一个EurekaServer进行重新请求。
那么疑问来了,EurekaClient每次请求真的是以配置的defaultZone配置的第一个服务节点作为请求的吗?这似乎也太弱了!!?
EurekaServer集群不就成了伪集群!!?除了客户端配置的第一个节点,其它注册中心的节点都只能作为备份和故障转移来使用!!?
真相是这样吗?NO!我们眼见也不一定为实,源码面前毫无秘密!
翠花,上干货!
客户端请求负载原理 原理图解还是先上结论,负载原理如图所示: