【AICon】探索RAG 技术在实际应用中遇到的挑战及应对策略!AICon精华内容已上线73%>>> 了解详情
写点什么

详解 Eureka 缓存机制

  • 2019-05-10
  • 本文字数:3511 字

    阅读完需:约 12 分钟

详解 Eureka 缓存机制

详解 Eureka 缓存机制

引言

Eureka 是 Netflix 开源的、用于实现服务注册和发现的服务。Spring Cloud Eureka 基于 Eureka 进行二次封装,增加了更人性化的 UI,使用更为方便。但是由于 Eureka 本身存在较多缓存,服务状态更新滞后,最常见的状况是:服务下线后状态没有及时更新,服务消费者调用到已下线的服务导致请求失败。本文基于 Spring Cloud Eureka 1.4.4.RELEASE,在默认 region 和 zone 的前提下,介绍 Eureka 的缓存机制。

AP 特性

从 CAP 理论看,Eureka 是一个 AP 系统,优先保证可用性(A)和分区容错性§,不保证强一致性©,只保证最终一致性,因此在架构中设计了较多缓存。



(Eureka 高可用架构)

服务状态

Eureka 服务状态 enum 类:com.netflix.appinfo.InstanceInfo.InstanceStatus


状态说明状态说明
UP在线OUT_OF_SERVICE失效
DOWN下线UNKNOWN未知
STARTING正在启动

Eureka Server

在 Eureka 高可用架构中,Eureka Server 也可以作为 Client 向其他 server 注册,多节点相互注册组成 Eureka 集群,集群间相互视为 peer。Eureka Client 向 Server 注册、续约、更新状态时,接受节点更新自己的服务注册信息后,逐个同步至其他 peer 节点。


【注意】如果 server-A 向 server-B 节点单向注册,则 server-A 视 server-B 为 peer 节点,server-A 接受的数据会同步给 server-B,但 server-B 接受的数据不会同步给 server-A。

缓存机制

Eureka Server 存在三个变量:(registry、readWriteCacheMap、readOnlyCacheMap)保存服务注册信息,默认情况下定时任务每 30s 将 readWriteCacheMap 同步至 readOnlyCacheMap,每 60s 清理超过 90s 未续约的节点,Eureka Client 每 30s 从 readOnlyCacheMap 更新服务注册信息,而 UI 则从 registry 更新服务注册信息。



三级缓存


缓存类型说明
registryConcurrentHashMap实时更新,类AbstractInstanceRegistry成员变量,UI端请求的是这里的服务注册信息
readWriteCacheMapGuava Cache/LoadingCache实时更新,类ResponseCacheImpl成员变量,缓存时间180秒
readOnlyCacheMapConcurrentHashMap周期更新,类ResponseCacheImpl成员变量,默认每30s从readWriteCacheMap更新,Eureka client默认从这里更新服务注册信息,可配置直接从readWriteCacheMap更新


缓存相关配置


配置默认说明
eureka.server.useReadOnlyResponseCachetrueClient从readOnlyCacheMap更新数据,false则跳过readOnlyCacheMap直接从readWriteCacheMap更新
eureka.server.responsecCacheUpdateIntervalMs30000readWriteCacheMap更新至readOnlyCacheMap周期,默认30s
eureka.server.evictionIntervalTimerInMs60000清理未续约节点(evict)周期,默认60s
eureka.instance.leaseExpirationDurationInSeconds90清理未续约节点超时时间,默认90s


关键类


类名说明
com.netflix.eureka.registry.AbstractInstanceRegistry保存服务注册信息,持有registry和responseCache成员变量
com.netflix.eureka.registry.ResponseCacheImpl持有readWriteCacheMap和readOnlyCacheMap成员变量

Eureka Client

Eureka Client 存在两种角色:服务提供者服务消费者,作为服务消费者一般配合 Ribbon 或 Feign(Feign 内部使用 Ribbon)使用。Eureka Client 启动后,作为服务提供者立即向 Server 注册,默认情况下每 30s 续约(renew);作为服务消费者立即向 Server 全量更新服务注册信息,默认情况下每 30s 增量更新服务注册信息;Ribbon 延时 1s 向 Client 获取使用的服务注册信息,默认每 30s 更新使用的服务注册信息,只保存状态为 UP 的服务。


二级缓存


缓存类型说明
localRegionAppsAtomicReference周期更新,类DiscoveryClient成员变量,Eureka Client保存服务注册信息,启动后立即向Server全量更新,默认每30s增量更新
upServerListZoneMapConcurrentHashMap周期更新,类LoadBalancerStats成员变量,Ribbon保存使用且状态为UP的服务注册信息,启动后延时1s向Client更新,默认每30s更新


缓存相关配置


配置默认说明
eureka.instance.leaseRenewalIntervalInSeconds30Eureka Client 续约周期,默认30s
eureka.client.registryFetchIntervalSeconds30Eureka Client 增量更新周期,默认30s(正常情况下增量更新,超时或与Server端不一致等情况则全量更新)
ribbon.ServerListRefreshInterval30000Ribbon 更新周期,默认30s


关键类


类名说明
com.netflix.discovery.DiscoveryClientEureka Client 负责注册、续约和更新,方法initScheduledTasks()分别初始化续约和更新定时任务
com.netflix.loadbalancer.PollingServerListUpdaterRibbon 更新使用的服务注册信息,start初始化更新定时任务
com.netflix.loadbalancer.LoadBalancerStatsRibbon,保存使用且状态为UP的服务注册信息

默认配置下服务消费者最长感知时间

Eureka Client时间说明
上线30(readOnly)+30(Client)+30(Ribbon)=90sreadWrite -> readOnly -> Client -> Ribbon 各30s
正常下线30(readonly)+30(Client)+30(Ribbon)=90s服务正常下线(kill或kill -15杀死进程)会给进程善后机会,DiscoveryClient.shutdown()将向Server更新自身状态为DOWN,然后发送DELETE请求注销自己,registry和readWriteCacheMap实时更新,故UI将不再显示该服务实例
非正常下线30+60(evict)*2+30+30+30=240s服务非正常下线(kill -9杀死进程或进程崩溃)不会触发DiscoveryClient.shutdown()方法,Eureka Server将依赖每60s清理超过90s未续约服务从registry和readWriteCacheMap中删除该服务实例


考虑如下情况


  • 0s 时服务未通知 Eureka Client 直接下线;

  • 29s 时第一次过期检查 evict 未超过 90s;

  • 89s 时第二次过期检查 evict 未超过 90s;

  • 149s 时第三次过期检查 evict 未续约时间超过了 90s,故将该服务实例从 registry 和 readWriteCacheMap 中删除;

  • 179s 时定时任务从 readWriteCacheMap 更新至 readOnlyCacheMap;

  • 209s 时 Eureka Client 从 Eureka Server 的 readOnlyCacheMap 更新;

  • 239s 时 Ribbon 从 Eureka Client 更新。


因此,极限情况下服务消费者最长感知时间将无限趋近 240s。


应对措施

服务注册中心在选择使用 Eureka 时说明已经接受了其优先保证可用性(A)和分区容错性§、不保证强一致性©的特点。如果需要优先保证强一致性©,则应该考虑使用 ZooKeeper 等 CP 系统作为服务注册中心。分布式系统中一般配置多节点,单个节点服务上线的状态更新滞后并没有什么影响,这里主要考虑服务下线后状态更新滞后的应对措施。

Eureka Server

  1. 缩短 readOnlyCacheMap 更新周期。缩短该定时任务周期可减少滞后时间。

  2. 关闭 readOnlyCacheMap。中小型系统可以考虑该方案,Eureka Client 直接从 readWriteCacheMap 更新服务注册信息。

Eureka Client

  1. 服务消费者使用容错机制。如 Spring Cloud Retry 和 Hystrix,Ribbon、Feign、Zuul 都可以配置 Retry,服务消费者访问某个已下线节点时一般报 ConnectTimeout,这时可以通过 Retry 机制重试下一个节点。

  2. 服务消费者缩短更新周期。Eureka Client 和 Ribbon 二级缓存影响状态更新,缩短这两个定时任务周期可减少滞后时间,例如配置:

  3. 服务提供者保证服务正常下线。服务下线时使用 kill 或 kill -15 命令,避免使用 kill -9 命令,kill 或 kill -15 命令杀死进程时将触发 Eureka Client 的 shutdown()方法,主动删除 Server 的 registry 和 readWriteCacheMap 中的注册信息,不必依赖 Server 的 evict 清除。

  4. 服务提供者延迟下线。服务下线之前先调用接口使 Eureka Server 中保存的服务状态为 DOWN 或 OUT_OF_SERVICE 后再下线,二者时间差根据缓存机制和配置决定,比如默认情况下调用接口后延迟 90s 再下线服务即可保证服务消费者不会调用已下线服务实例。

网关实现服务下线实时感知

在软件工程中,没有一个问题是中间层解决不了的,而网关是服务提供者和服务消费者的中间层。以 Spring Cloud Zuul 网关为例,网关作为 Eureka Client 保存了服务注册信息,服务消费者通过网关将请求转发给服务提供者,只需要做到服务提供者下线时通知网关在自己保存的服务列表中使该服务失效。为了保持网关的独立性,可实现一个独立服务接收下线通知并协调网关集群。


原文链接


http://college.creditease.cn/detail/243


2019-05-10 08:0012484

评论 1 条评论

发布
用户头像
女子
2019-05-11 23:30
回复
没有更多了
发现更多内容

互联网架构师能力图谱

dony.zhang

架构师 架构师技能

拖动旋转的 3D 骰子效果

Clloz

CSS transform rotate3d

轻松的可贵

谷鱼

回忆 转折

第一周作业

alpha

极客大学架构师训练营

技术解析丨C++元编程之Parser Combinator

华为云开发者联盟

c++ 字符串 Parser Combinator Parser 元编程

LeetCode题解:84. 柱状图中最大的矩形,使用栈,JavaScript,详细注释

Lee Chen

大前端 LeetCode

架构师训练营大作业

方堃

架构师训练营-大作业

连增申

食堂就餐系统 UML 图

睁眼看世界

极客大学架构师训练营 食堂就餐系统

第一周总结

睁眼看世界

极客大学架构师训练营

有了数据湖探索服务,企业决策“新”中有数

华为云开发者联盟

Serverless 数据湖 数据分析 云原生 华为云

为什么我选择清晨阅读和学习

胡迪伦

学习 效率 自学编程 早起 晨型人

思维导图

纯纯

架构师训练营大作业

Bruce Xiong

架构师训练营大作业二(架构思维导图)

吴建中

大作业-同城快递

林毋梦

在进行廋身之前,对你来说是想要找到问题的真相?或是解决当下的问题?

叶小鍵

心理学 基思·斯坦诺维奇

Skywalking Php注册不上问题排查

心平气和

php Skywalking 全链路追踪

使用枚举的正确姿势

Java旅途

Java 单例 枚举

期末作业-达通快递

森林

oeasy 教您玩转 linux 之 010301 电子宠物 pet

o

C++隐式推导-auto关键词

良知犹存

c++

LeetCode题解:66. 加一,BigInt,JavaScript,详细注释

Lee Chen

大前端 LeetCode

Golang领域模型-聚合根

奔奔奔跑

架构 微服务 领域驱动设计 DDD Go 语言

架构师训练营大作业

努力努力再努力m

架构师训练营第 1 期第一次作业

强风

大作业二

嘻哈

架構師訓練營第1期-第01周總結

Panda

架构师训练营-week01-作业

大刘

极客大学架构师训练营

系统架构师训练营大作业(一)-同城物流快递业务系统架构设计

吴建中

“锟斤拷”的前世今生

Java旅途

Unicode 编码 ASCII 锟斤拷

详解 Eureka 缓存机制_架构_冯永彪_InfoQ精选文章