某年某月某日,像一张破脸。..错了,再试一次。某日,突然发现大量告警。经过多方调查排查(这里省略3000字),发现报错是因为Eureka服务下线太慢,但是还是有大量的请求进来。于是,经过大量的详细细致的调查研究,终于找到问题并解决了(此处省略5000字)。全文结束。……嗯,那是不可能的,所以我必须写300个字来做一个原创。为什么在服务离线的情况下,仍然有那么多请求进来?现在,我们都知道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秒。好了,今天就到这里。我是艾小娴。下次见。
