原文:https://www.cnblogs.com/yixinjishu/p/10871243.html

引言

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

一、AP特性

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

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。

3.1 缓存机制

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

三级缓存

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

缓存相关配置

配置 默认 说明
eureka.server.useReadOnlyResponseCache true Client从readOnlyCacheMap更新数据,false则跳过readOnlyCacheMap直接从readWriteCacheMap更新
eureka.server.responsecCacheUpdateIntervalMs 30000 readWriteCacheMap更新至readOnlyCacheMap周期,默认30s
eureka.server.evictionIntervalTimerInMs 60000 清理未续约节点(evict)周期,默认60s
eureka.instance.leaseExpirationDurationInSeconds 90 清理未续约节点超时时间,默认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的服务。

二级缓存

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

缓存相关配置

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

关键类

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

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

Eureka Client 时间 说明
上线 30(readOnly)+30(Client)+30(Ribbon)=90s readWrite -> 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)和分区容错性(P)、不保证强一致性(C)的特点。如果需要优先保证强一致性(C),则应该考虑使用ZooKeeper等CP系统作为服务注册中心。分布式系统中一般配置多节点,单个节点服务上线的状态更新滞后并没有什么影响,这里主要考虑服务下线后状态更新滞后的应对措施。

6.1 Eureka Server

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

    eureka.server.responsecCacheUpdateIntervalMs: 10000  # Eureka Server readOnlyCacheMap更新周期
  • 2.关闭readOnlyCacheMap。中小型系统可以考虑该方案,Eureka Client直接从readWriteCacheMap更新服务注册信息。

    eureka.server.useReadOnlyResponseCache: false        # 是否使用readOnlyCacheMap

6.2 Eureka Client

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

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

    eureka.client.registryFetchIntervalSeconds: 5        # Eureka Client更新周期
    ribbon.ServerListRefreshInterval: 2000 # 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保存了服务注册信息,服务消费者通过网关将请求转发给服务提供者,只需要做到服务提供者下线时通知网关在自己保存的服务列表中使该服务失效。为了保持网关的独立性,可实现一个独立服务接收下线通知并协调网关集群。

详解Eureka 缓存机制的更多相关文章

  1. 程序员笔记|详解Eureka 缓存机制

    引言 Eureka是Netflix开源的.用于实现服务注册和发现的服务.Spring Cloud Eureka基于Eureka进行二次封装,增加了更人性化的UI,使用更为方便.但是由于Eureka本身 ...

  2. 详解浏览器缓存机制与Apache设置缓存

    一.详解浏览器缓存机制 对于,如何说明缓存机制,在网络上找到了两张图,个人认为思路是比较清晰的.总结时,上图. 这里需要注意的有两点: 1.Last-Modified.Etag是响应头里的数据 2.I ...

  3. 浏览器 HTTP 协议缓存机制详解--网络缓存决策机制流程图

    1.缓存的分类 2.浏览器缓存机制详解 2.1 HTML Meta标签控制缓存 2.2 HTTP头信息控制缓存 2.2.1 浏览器请求流程 2.2.2 几个重要概念解释 3.用户行为与缓存 4.Ref ...

  4. 百度地图API详解之事件机制,function“闭包”解决for循环和监听器冲突的问题:

    原文:百度地图API详解之事件机制,function"闭包"解决for循环和监听器冲突的问题: 百度地图API详解之事件机制 2011年07月26日 星期二 下午 04:06 和D ...

  5. Linux上的free命令详解、swap机制

    Linux上的free命令详解   解释一下Linux上free命令的输出. 下面是free的运行结果,一共有4行.为了方便说明,我加上了列号.这样可以把free的输出看成一个二维数组FO(Free ...

  6. day09 详解内存管理机制

    """ 今日内容:详解内存管理 1.引用计数 在内存中为了对变量的值进行标记从而方便管理,采用引用计数的方式对变量进行标记. (1)如果变量的值被引用一次,那么该变量的引 ...

  7. 详解HTTP缓存

    HTTP缓存是个大公司面试几乎必考的问题,写篇随笔说一下HTTP缓存. 1. HTTP报文首部中有关缓存的字段 在HTTP报文中,与缓存相关的信息都存在首部里,简单说一下首部. 首部 HTTP首部字段 ...

  8. Android AIDL使用详解_Android IPC 机制详解

    一.概述 AIDL 意思即 Android Interface Definition Language,翻译过来就是Android接口定义语言,是用于定义服务器和客户端通信接口的一种描述语言,可以拿来 ...

  9. 详解 WebAPI 签名机制

    首先,写这篇文章的原因是因为最近某一个项目中的接口被人为调用了,导致了数据库数据被串改.虽然是内部人无意点的,但还是引起了我的担忧,所有整理了下关于WebAPI的相关签名机制. 一.我们在开发接口时, ...

随机推荐

  1. nginx学习,看这一篇就够了:下载、安装。使用:正向代理、反向代理、负载均衡。常用命令和配置文件

    前言一.nginx简介1. 什么是 nginx 和可以做什么事情Nginx 是高性能的 HTTP 和反向代理的web服务器,处理高并发能力是十分强大的,能经受高负 载的考验,有报告表明能支持高达 50 ...

  2. Java 集合系列之三:Set基本操作

    1. Java Set 1. Java Set 重要观点 Java Set接口是Java Collections Framework的成员. Set不允许出现重复元素-----------无重复 Se ...

  3. concurrent (二)AQS

    参考文档: https://www.cnblogs.com/waterystone/p/4920797.html

  4. 将物理机转换成vmware虚机

    随着虚拟化的快速发展,公司主要是以公有云+私有云结合的混合云部署,据我不成熟的了解,目前很少有公司会将一台单独的物理机作为服务器,在公司内部大家逐渐接受了私有云的部署方案,这样做不但可以节省硬件资源, ...

  5. hive 批量添加,删除分区

    一.批量添加分区:   use bigdata; alter table siebel_member add if not exists partition(dt='20180401') locati ...

  6. 测试效率加倍提升!shell 高阶命令快来 get 下!

    背景 目前大部分的项目都是部署在Linux系统上,作为测试,掌握常用Linux命令是必须的技能.很多的工作了好几年的测试人员可能还只会简单的ls.cd.cat等等这些命令,这些命令是可以应付工作的大部 ...

  7. docker 学习操作记录 5-1

    记录5-1 [BEGIN] // :: Connecting to ... Connection established. To escape to local shell, press Ctrl+A ...

  8. Linux内核device结构体分析

    1.前言 Linux内核中的设备驱动模型,是建立在sysfs设备文件系统和kobject上的,由总线(bus).设备(device).驱动(driver)和类(class)所组成的关系结构,在底层,L ...

  9. Python学习教程(十)精选 TOP45 值得学习的Python项目

    精选 TOP45 值得学习的Python项目 [导读]热门资源博客 Mybridge AI 比较了 18000 个关于 Python 的项目,并从中精选出 45 个最具竞争力的项目.我们进行了翻译,在 ...

  10. angualr post 数据请求

    数据请求 post 新建一个服务 1. ng g service services /+服务名  eg:ng g service services/player 在此服务中进行设置 引入自带组件以及注 ...