一、服务注册慢的问题
在我们启动一个服务后,可能要过一分多钟才能被其他服务调用到,那么这种情况不管是开发/测试环境,亦或是生产环境都会影响效率。出现该问题的原因有以下几种:
-
Eureka Server缓存
Eureka Server的两级缓存策略,在ResponseCacheImpl类中有readWriteCacheMap读写缓存和readOnlyCacheMap只读缓存,readWriteCacheMap缓存周期为180秒,readOnlyCacheMap会周期更新,默认每30秒从readWriteCacheMap更新至readOnlyCacheMap,客户端请求时默认会先从readOnlyCacheMap获取数据,获取不到数据的情况下,会从readWriteCacheMap中获取,相关逻辑在ResponseCacheImpl中可以找到。
可以通过eureka.server.response-cache-update-interval-ms参数配置readOnlyCacheMap的更新频率(默认30秒),也可以通过eureka.server.use-read-only-response-cache=false(默认为true)参数配置来禁用readOnlyCacheMap。
-
Eureka Client缓存
客户端会定期的从Eureka Server获取最新的服务注册信息,默认为30秒,通过eureka.client.registry-fetch-interval-seconds参数可以配置更新周期
-
Ribbon缓存
Ribbon的负载平衡器从本地的Eureka Client获取服务注册列表信息。Ribbon本身还维护本地缓存,以避免为每个请求调用本地客户端。 此缓存每30秒刷新一次,通过ribbon.ServerListRefreshInterval参数可以配置
所以终上所述,一个服务注册上线需要的最大时间为30(eureka.server.response-cache-update-interval-ms)+30(eureka.client.registry-fetch-interval-seconds)+30(ribbon.ServerListRefreshInterval)=90秒。
二、服务注销慢的问题
在服务停掉后,Eureka Server并不能快速的将已停止的服务实例剔除,对调用方而言,请求到已停止的服务实例上则会提示拒绝连接,出现该问题的原因有以下几种:
-
Eureka Server失效服务剔除
Eureka Server,默认每60秒会检测失效的服务,检测标准就是超过一定时间(默认90秒)没有renew续约的服务,也就是如果有服务超过90秒没有向Eureka Server发起Renew请求的话,就会被当做失效服务剔除掉。通过参数eureka.server.eviction-interval-timer-in-ms配置,单位为毫秒
-
Eureka Client周期心跳
Eureka Client需要定期向Eureka Server发送心跳已续约自已的租期,避免被Eureka Server剔除,默认为30秒。通过eureka.instance.lease-renewal-interval-in-seconds参数配置。此外参数eureka.instance.lease-expiration-duration-in-seconds表示Eureka服务器在接收到实例的最后一次发出的心跳后,需要等待多久才可以将此实例删除,默认90秒
三、服务注册/注销慢的解决方案
综合以上服务注册慢/注销慢的原因,我们的解决方案其实就是将上述的一些参数时间缩短。参考配置如下:
- Eureka Server端配置
#关闭自我保护模式
eureka.server.enable-self-preservation=false
#Eureka Server清理无效节点的频率,单位:毫秒,默认60秒
eureka.server.eviction-interval-timer-in-ms=5000
#禁用readOnlyCacheMap
eureka.server.use-read-only-response-cache=false
- Eureka Client端配置
#从eureka服务端获取配置
eureka.client.fetch-registry = true
#将自身的服务注册至eureka服务端
eureka.client.register-with-eureka = true
#通过IP注册
eureka.instance.prefer-ip-address = true
#指示从Eureka服务器获取注册表信息的频率(秒),默认30秒
eureka.client.registry-fetch-interval-seconds=5
#客户端向Eureka服务器发送心跳以续约自已的租期,默认30秒
eureka.instance.lease-renewal-interval-in-seconds=5
#Eureka服务器在接收到实例的最后一次发出的心跳后,需要等待多久才可以将此实例删除,默认90秒
eureka.instance.lease-expiration-duration-in-seconds=5
#Ribbon更新服务注册列表的频率
ribbon.ServerListRefreshInterval=2000
上述的配置只适用于中小型应用,需要注意的是,如果把请求Eureka Server的时间都调小的话(比如获取注册表、发送心跳等),在系统服务实例的数量很大的情况下,那么会对Eureka Server造成压力。
四、关于自我保护机制
如果Eureka服务节点在短时间里丢失了大量客户端的心跳连接时,(注:可能发生了网络故障,有可能客户端实例还在正常运行),那么这个Eureka节点会进入”自我保护模式“,同时保留那些“心跳死亡“的服务注册信息不过期。此时,这个Eureka节点对于新的服务还能提供注册服务,对于”死亡“的仍然保留,以防还有客户端向其发起请求。当网络故障恢复后,这个Eureka节点会退出”自我保护模式“。所以Eureka的哲学是,同时保留”好数据“与”坏数据“总比丢掉任何”好数据“要更好。
对于不存在跨区、跨网络机房的中小型应用而言,建议关闭自我保护模式。
五、推荐阅读:
如果文章对你有帮助的话,给文章点个赞吧。
如果有写得不正确的地方,欢迎指出。
文章首发公众号:会跳舞的机器人,欢迎扫码关注。