当前位置: 首页 > 科技观察

Eureka服务下线太慢的惨痛经历!

时间:2023-03-15 15:50:28 科技观察

这一天,突然发现大量报警。经过多方排查排查,发现报错是因为Eureka服务下线太慢,但是还是有大量的请求进来。于是,经过大量详细细致的排查和研究,我终于找到了问题并解决了。为什么在服务离线的情况下,仍然有那么多请求进来?现在,我们都知道Eureka是一个AP模型。其实根本原因是Eureka使用了三级缓存来保存服务实例信息。如下图所示:当我们的服务注册后,会与服务器保持心跳。心跳时间为30秒。服务注册后,客户端的实例信息保存在Registry服务注册中心,注册中心的信息会立即同步。进入readWriteCacheMap。而如果客户端感知到这个服务,则需要从readOnlyCacheMap中读取。此只读缓存需要30秒才能从readWriteCacheMap同步。客户端和Ribbon负载均衡器都维护一个本地缓存,每30秒同步一次。根据以上,我们来计算一下客户端需要多长时间才能感知到服务下线的极端情况。客户端每30秒向服务器发送一次心跳。注册中心保存了所有服务注册的实例信息。它会与readWriteCacheMap保持实时同步,readWriteCacheMap和readOnlyCacheMap每30秒同步一次。客户端每30秒同步一次readOnlyCacheMap的注册实例信息。考虑到如果ribbon用于负载均衡,它还有一层缓存,每30秒同步一次。如果一个服务正常下线,在极端情况下,时间应该是30+30+30+30差不多120秒。如果服务异常下线,需要依赖每60秒执行一次的清理线程,将超过90秒没有心跳的服务剔除。这里极端情况下,可能需要3次60秒才能检测到,也就是180秒。最长可能累计感知时间为:180+120=300秒,5分钟。这次有点夸张了。如果考虑到某些中间件可能是多余的,再加上一些清理工作,这一次简直就是灾难性的。的。然后有人问,我在Eureka控制台看到服务上下线很快,你不是在开玩笑吗?大哥,控制台显示的是直接获取到的Registry信息,所以肯定很快,所以不能这样判断。那怎么解决呢?解决办法当然是改变这些时间。这个时间需要根据实际生产情况来判断和修改。这里只是一个例子。修改ribbon同步缓存时间为3秒:ribbon.ServerListRefreshInterval=3000修改客户端同步缓存时间为3秒:eureka.client.registry-fetch-interval-seconds=3修改心跳间隔为3秒:eureka.instance。lease-renewal-interval-in-seconds=3超时淘汰时间改为9秒:eureka.instance.lease-expiration-duration-in-seconds=9清洗线程计时改为5秒执行一次:尤里卡服务器。eviction-interval-timer-in-ms=5000同步到只读缓存的时间改为每3秒一次:eureka.server.response-cache-update-interval-ms=3000需要注意的是这里的read-onlycache其实是可以通过修改参数eureka.server.use-read-only-response-cache=false来关闭的,但是建议非必要不要这样做。Eureka本身就是一个AP模型。你可以使用它你应该有这个意识。另外,这个配置只对原生的Eureka有效。SpringCloudEureka没有。它必须从readOnlyCacheMap中读取。如果按照这个时间参数设置,我们重新计算一下我们可能感知到服务下线的最长时间:正常下线是3+3+3+3=12秒,异常下线加上15秒就是27秒。