Eureka 默认配置存在的问题
根据 eureka 官方wiki 上对于客户端服务端描述中有一段话写到(见截图)。大概意思是 一个服务启动后最长可能需要2分钟时间才能被其它服务感知到。而且,服务的下线后,客户端感知到某服务下线所用时间可能会更长。
但是2分钟的时长对于生产环境来说是不可接受的。本文将解释eureka 的默认配置为什么会出现 最多2分钟的情况,以及优化的方法。
问题原因分析
下面我们根据 Eureka 原理图分析一下问题出现的原因。
问题的原因,总体来说是因为线程定时刷新缓存的时间差。
首先服务B启动成功后 30 秒 发送心跳给服务端,服务端记录信息到 服务注册表中。
30秒之后,定时检查服务注册表的线程,发现有新的服务。此时将新服务放入 ReadWrite缓存中。
30秒之后,缓存同步线程,将ReadWrite缓存中的 服务注册表,同步到 ReadOnly 缓存。
服务A 负载均衡组件Ribbon 30 秒之后,去获取 ReadOnly 缓存中的注册表,并缓存到 Ribbon中。
所以加起来 一共是 120 秒 也就是 两分钟。这里要注意的是,SpringCloud 优化过启动成功就会立即发送心跳,所以首次启动不需要等待 30 秒发送心跳,最多应该是 1分30秒时间。
优化方法
上面的问题,主要是监控线程定时刷新时间过长,每一步操作都需要 30 秒时间才会同步最新的注册表数据,我们可以通过配置,缩短 线程定时同步时间 来进行优化。
针对此问题,我们可优化 5 个参数的配置。下面是这些参数名称及默认配置。
- 服务端
- 读写缓存与只读缓存定时间隔 : eureka.server.responseCacheUpdateIntervalMs=30000
- 检查注册表数据定时时间间隔 : eureka.server.evictionIntervalTimerInMs=30000
- 客户端
- 客户端获取最新服务注册表时间间隔 : eureka.client.registryFetchIntervalSeconds=30
- 客户端定时发送心跳时间间隔 : eureka.client.leaseRenewalIntervalInSeconds=30
- 配置客户端多少秒没有心跳就从服务端移除该服务 : eureka.client.leaseExpirationDurationInSeconds=90
我们可以将默认时间间隔 提速 10倍,服务发现的相关参数 从 30 秒配置为 3秒。服务下线也从 90 秒无心跳,提升为 9 秒,这样客户端可以及时感知到服务的新增与停止。
如何还想继续优化,可以直接关闭 只读缓存的同步,直接使用 读写缓存。配置在服务端,默认配置为 true,具体如下:
- eureka.server.useReadOnlyResponseCache = false
参考:https://apppukyptrl1086.pc.xiaoe-tech.com/detail/p_5d3114935b4d7_CEcL8yMS/6