Netflix Eureka - Eureka Client 全量拉取注册表/Eureka Server 注册表多级缓存机制

226 阅读3分钟

本文已参与「新人创作礼」活动,一起开启掘金创作之路。

  1. eureka server启动以及初始化

  2. eureka client启动以及初始化

  3. eureka client发送服务实例的注册

  4. eureka server接收服务实例的注册

  5. eureka client抓取全量注册表

eureka client抓取全量注册表

全量注册表

eureka client启动,从eureka server端抓取全量注册表信息,在本地进行缓存。

增量注册表

每隔30秒从eureka server抓取增量注册表信息,与本地缓存的全量注册表合并

如果配置抓取注册表eureka.shouldFetchRegistry,就会在启动的时候抓取一次全量注册表。

抓取全量注册表

(1)EurekaClient初始化的时候,就会自动抓取全量注册表

(2)先获取本地的Applications缓存(此时是空的)

Applications:就是所有的服务,Applicaiton是一个服务,Applications是所有的服务

Application:包含服务自己的所有的服务实例(InstanceInfo)

application是{appName:[instanceId]}的关系,applications就是[application]的关系

(3)本地的Application缓存是空,调用getAndStoreFullRegistry方法,拉取并缓存全量注册表

(4)调用jersey client(eurekaTransport.queryClient.getApplications()),发送http请求(http://localhost:8080/v2/apps ),GET请求,调用eureka server的getApplications restful接口,获取全量注册表,缓存在自己的本地

eureka server注册表多级缓存机制

eureka server调用ApplicationsResource的getContainers()方法,处理抓取全量注册表的请求。

Accept-Encoding: gzip, deflate ,表示这个请求的响应内容希望被压缩, 如果服务器不支持压缩或者没有开启压缩,则不能起到作用。

Content-Encoding: 如果服务器也是支持压缩或者开启压缩,则会在响应头中加入Content-Encoding: gzip 头部

X-Eureka-Accept:通过调用EurekaAccept.fromString(eurekaAccept)获得客户端接收的是full还是compact

构造Key

cacheKey:全量注册表的缓存key

entityType:缓存值的数据类型(Application, VIP, SVIP)

entityName:缓存值的名称(ALL_APPS, ALL_APPS_DELTA)

requestType:缓存值的序列化类型(json、xml)

requestVersion:缓存值的版本号

eurekaAccept:响应类型

regions:远程服务域

eureka client发送请求读取全量注册表,从多级缓存里去读取注册表的数据

ResponseCache

ResponseCache,就是eureka server端的缓存机制

ApplicationResource构造函数内初始化ResponseCache responseCache = registry.getResponseCache();

responseCache.getGZIP(cacheKey) 或 responseCache.get(cacheKey) 从多级缓存里查询Applications返回。

多级缓存机制(ResponseCache)

只读缓存

ConcurrentMap<Key, Value> readOnlyCacheMap

读写缓存

LoadingCache<Key, Value> readWriteCacheMap;

多级缓存机制:用两个map做两级缓存,只读缓存map,读写缓存map。

先从只读缓存里去读,如果没有的话,会从读写缓存里去读,如果还是没有,会从eureka server的注册表中去读取

为什么使用多级缓存?

避免同时读写内存数据结构造成的并发冲突问题,使写操作不阻塞读操作

当存在大规模的服务注册和更新时,如果只是修改一个ConcurrentHashMap数据,那么势必因为锁的存在导致竞争,影响性能。

Eureka又是AP模型,只需要满足最终可用就行。所以它在这里用到多级缓存来实现读写分离。注册方法写的时候直接写内存注册表,写完表之后主动失效读写缓存。

获取注册信息接口先从只读缓存取,只读缓存没有再去读写缓存取,读写缓存没有再去内存注册表里取(不只是取,此处较复杂)。并且,读写缓存会更新回写只读缓存