Eureka造成延迟的原因:有三处缓存+一次延迟造成的。
1、Eureka对HTTP响应做了缓存。
// 从cache中拿响应数据
String payLoad = responseCache.get(cacheKey);
if (payLoad != null) {
logger.debug("Found: {}", appName);
return Response.ok(payLoad).build();
} else {
logger.debug("Not Found: {}", appName);
return Response.status(Status.NOT_FOUND).build();
}
上面的代码中,responseCache引用的是ResponseCache类型,该类型是一个接口,其get()方法首先会去缓存中查询数据,如果没有则生成数据返回(即真正去查询注册列表),且缓存的有效时间为30s。也就是说,客户端拿到Eureka的响应并不一定是即时的,大部分时候只是缓存信息。
2、Eureka Client对已经获取到的注册信息也做了30s缓存。即服务通过eureka客户端第一次查询到可用服务地址后会将结果缓存,下次再调用时就不会真正向Eureka发起HTTP请求了。
3、 负载均衡组件Ribbon也有30s缓存。Ribbon会从上面提到的Eureka Client获取服务列表,然后将结果缓存30s。
4、如果你并不是在Spring Cloud环境下使用这些组件(Eureka, Ribbon),你的服务启动后并不会马上向Eureka注册,而是需要等到第一次发送心跳请求时才会注册。心跳请求的发送间隔也是30s。(Spring Cloud对此做了修改,服务启动后会马上注册)
降低延迟的方式:
1.降低延迟时间
2.增加重试机制
方法:在网关、Fegin或者Ribbon上面添加请求重试机制。
优化后server配置:
## 禁用readOnlyCacheMap
eureka.server.useReadOnlyResponseCache=false
## 中小规模下,自我保护模式坑比好处多,所以关闭它
eureka.server.enableSelfPreservation=false
## 主动失效检测间隔,配置成5秒
eureka.server.evictionIntervalTimerInMs=5000
## 心跳间隔,5秒
eureka.instance.leaseRenewalIntervalInSeconds=5
## 没有心跳的淘汰时间
eureka.instance.leaseExpirationDurationInSeconds=10
client端
## 心跳间隔,5秒
eureka.instance.leaseRenewalIntervalInSeconds=5
## 没有心跳的淘汰时间,10秒
eureka.instance.leaseExpirationDurationInSeconds=10
# 定时刷新本地缓存时间
eureka.client.registryFetchIntervalSeconds=5
# ribbon缓存时间
ribbon.ServerListRefreshInterval=2000