一文给你道破Eureka服务发现慢的原因,深度剖析Eureka客户端服务发现原理以及 Eureka服务端服务剔除原理

本文深入剖析Eureka服务发现原理,包括服务端和客户端缓存机制,服务下线和失效剔除过程。揭示Eureka自我保护机制的作用,探讨在网络分区时如何保持服务可用性,并提供了配置优化建议,以提高服务发现效率。
摘要由CSDN通过智能技术生成

我的博客,原文出处http://www.deepinblog.com/eureka/175/

我的博客地址,原文出处

先直接给出配置让你尝鲜

EurekaServer端配置

eureka:
  server:
    #Eureka Server会定时(间隔值是eureka.server.eviction-interval-timer-in-ms,默认60s)进行检查,如果发现实例在在一定时间
    #(此值由客户端设置的eureka.instance.lease-expiration-duration-in-seconds定义,默认值为90s)内没有收到心跳,则会注销此实例。
    #我们这里配置每秒钟去检测一次,驱除失效的实例
    eviction-interval-timer-in-ms: 1000
    #关闭一级缓存,让客户端直接从二级缓存去读取,省去各缓存之间的同步的时间
    use-read-only-response-cache: false

EurekaClient端(应用端)配置

eureka:
  client:
    service-url:
      defaultZone: http://localhost:8761/eureka/
    # EurekaClient每隔多久从EurekaServer拉取一次服务列表,默认30秒,这里修改为2秒钟从注册中心拉取一次
    registry-fetch-interval-seconds: 2
  #租约期限以及续约期限的配置
  instance:
    #租约到期,服务失效时间,默认值90秒,服务超过90秒没有发生心跳,EurekaServer会将服务从列表移除
    #这里修改为6秒
    lease-expiration-duration-in-seconds: 6
    #租约续约间隔时间,默认30秒,这里修改为3秒钟
    lease-renewal-interval-in-seconds: 3

#这里是Ribbon缓存实例列表的刷新间隔,默认30秒钟,这里修改为每秒钟刷新一次实例信息
ribbon:
  ServerListRefreshInterval: 1000

下面给你剖析原理

Eureka服务端详解

服务端缓存

如图所示

file

服务注册到注册中心后,服务实例信息是存储在注册表中的,也就是内存中。但Eureka为了提高响应速度,在内部做了优化,加入了两层的缓存结构,将Client需要的实例信息,直接缓存起来,获取的时候 直接从缓存中拿数据然后响应给 Client。

第一层缓存是readOnlyCacheMap,readOnlyCacheMap是采用ConcurrentHashMap来存储数据的,主要负责定时与readWriteCacheMap进行数据同步,默认同 步时间为 30 秒一次。

第二层缓存是readWriteCacheMap,readWriteCacheMap采用Guava来实现缓存。缓存过期时间默认为180秒,当服务下线、过期、注册、状态变更等操作都会清除此缓存中的数据。

第三层是数据存储层。

Client获取服务实例数据时,会先从一级缓存中获取,如果一级缓存中不存在,再从二级缓存中获取,如果二级缓存也不存在,会触发缓存的加载,从存储层拉取数据到缓存中,然后再返回给 Client。

Eureka 之所以设计二级缓存机制,也是为了提高 Eureka Server 的响应速度,缺点是缓存会导致 Client 获取不到最新的服务实例信息,然后导致无法快速发现新的服务和已下线的服务。

了解了服务端的实现后,想要解决这个问题就变得很简单了,我们可以缩短只读缓存的更新时间 (eureka.server.response-cache-update-interval-ms)让服务发现变得更加及时,或者直接将只读缓 存关闭(eureka.server.use-read-only-response-cache=false),多级缓存也导致Client层面(数据一致性)很薄弱。

客户端缓存

客户端缓存主要分为两块内容,一块是 Eureka Client 缓存,一块是 Ribbon 缓存。

Eureka Client缓存 ,EurekaClient负责跟EurekaServer进行交互,在EurekaClient中的 com.netflix.discovery.DiscoveryClient.initScheduledTasks() 方法中,初始化了一个 CacheRefreshThread 定时任务专⻔用来拉取 Eureka Server 的实例信息到本地。所以我们需要缩短这个定时拉取服务信息的时间间隔(此值在客户端配置eureka.client.registryFetchIntervalSeconds) 来快速发现新的服务

Ribbon缓存,Ribbon会从EurekaClient中获取服务信息,ServerListUpdater是Ribbon中负责服务实例 更新的组件,默认的实现是PollingServerListUpdater,通过线程定时去更新实例信息。定时刷新的时 间间隔默认是30秒,当服务停止或者上线后,这边最快也需要30秒才能将实例信息更新成最新的。我们可以将这个时间调短一点,比如 3 秒。

刷新间隔的参数是通过 getRefreshIntervalMs 方法来获取的,方法中的逻辑也是从 Ribbon的配置中进行取值的。所以我们需要缩短这个更新间隔(此值在客户端配置ribbon.ServerListRefreshInterval)来快速的更新Ribbon缓存实例列表

将这些服务端缓存和客户端缓存的时间全部缩短后,跟默认的配置时间相比,快了很多。我们通过调整 参数的方式来尽量加快服务发现的速度,但是还是不能完全解决报错的问题,间隔时间设置为3秒,也还是会有间隔。所以我们一般都会开启重试功能,当路由的服务出现问题时,可以重试到另一个服务来 保证这次请求的成功。

服务端缓存部分源码如下:

/**
 *The class that is responsible for caching registry information that will be
 *queried by the clients.
 */
public class ResponseCacheImpl implements ResponseCache {
   
    //一级缓存
  	private final ConcurrentMap<Key, Value> readOnlyCacheMap = new ConcurrentHashMap<Key, Value>();
    //二级缓存(Guava实现)
  	private final LoadingCache<Key, Value> readWriteCacheMap;
    //数据存储层
    private final AbstractInstanceRegistry registry
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值