Eureka问题汇总
Eureka心跳续约一直失败
由于服务端配置了30s无心跳则剔除注册的服务,当客户端由于网络波动等原因在一定时间内一直心跳失败时,就会出现一种很奇怪的现象:
服务端上注册的服务状态一直在上线、下线之间跳动,并且该服务一会消失、一会出现,此时客户端直接执行注册、上线、下线脚本都是正常的,观察日志会发现只有心跳一直失败,且心跳由最初配置的10s一次变成了100s一次,这个客户端服务在服务端的注册状态一直处于不稳定状态。
在翻看源码后发现,心跳任务由定时任务线程池执行,当心跳失败后会触发延时执行,每次翻倍,直到最初配置的10倍时间。由于配置的心跳间隔是10s,当出现网络波动后第一次心跳失败,下一次执行间隔变为20s,在连续失败几次后就达到了最大延时的100s。只有在成功触发一次心跳后,才会恢复为最初的10s。(源码看com.netflix.discovery.TimedSupervisorTask
)
按理说在网络问题修复后,应该就恢复正常的心跳间隔,实际上一直都维持着100s一次的心跳间隔。原因是服务端只要心跳超过30s就剔除服务,此时心跳必然失败,无法恢复为10s一次的心跳间隔,导致服务端的服务状态永远异常、客户端心跳永远失败的死循环。
由于业务要求服务端注册的服务实时性高,心跳间隔和心跳剔除时间改动不了,只能从心跳任务线程池入手,将心跳失败后的间隔扩容系数从原本的10调整为1,这样心跳失败后依然保持原本配置的10s,就不会发生这个问题了。
由于没有找到对应的属性配置,只能改动Eureka的源码,重写了com.netflix.discovery.PropertyBasedClientConfigConstants
的DEFAULT_EXECUTOR_THREAD_POOL_BACKOFF_BOUND
的值。临时应急的处理方法是直接重启客户端,但如果不改源码,以后依然会触发这种问题。