Eureka架构
Eureka 由 Eureka Server 和 Eureka Client 两部分组成:
- Server 是服务注册中心,负责维护集群中的服务实例信息和状态,以及给 Client 返回服务列表。在分布式环境下一般会多实例部署来达到高可用,比如在多个可用区上均部署 Eureka Server;
- Client 是一个嵌入到业务服务的模块,负责与 Server 交互,包括发送注册请求、维持心跳、拉取服务列表等;
- 引入了服务发现中心后,需要为其他应用提供服务的应用在启动时需要先通过 Eureka Client 向 Eureka Server 发送注册请求,把自己的服务信息注册到 Eureka Server 上,同时需要定期发送心跳。在应用下线时发送取消注册请求,把自身从 Eureka Server 的服务列表里删除;
Eureka工作原理
- client-A向server发起服务注册请求
- client-A默认每个30s向server发送心跳
- server每个90s检查一次 剔除下线的服务
- client-B向server发起注册请求,初次全量拉去
- 先到从server的只读缓存中获取(一级),如果获取不到,再去读写缓存中获取(二级),如果获取不到再去注册表缓存中读取(三级)
- client-B默认每个30s向server增量拉去注册表
- 同时读写注册表缓存中数据发生变化,会是读写缓存失效,30s同步到只读缓存
Eureka 的自我保护/服务摘除/服务续约
- Eureka 心跳机制:每个服务每隔 30s 自动向 Eureka Server 发送一次心跳,Eureka Server 更新这个服务的最后心跳时间。如果 180 s 内(版本1.7.2)未收到心跳,则任务服务故障了;
- Eureka 自我保护机制:如果上一分钟实际的心跳次数,比我们期望的心跳次数要小,就会触发自我保护机制,不会摘除任何实例。期望的心跳次数:服务实例数量 * 2 * 0.85;
- Eureka 服务摘除机制:不是一次性将服务实例摘除,每次最多随机摘除 15%。如果摘除不完,1 分钟之后再摘除;
各个服务的注册、服务下线、服务故障,全部会在内存里维护和更新注册表,各个服务每隔30秒拉取注册表的时候,Eureka Server就是直接提供内存里存储的有变化的注册表数据给他们就可以了;同样每隔30秒发起心跳时,也是在这个纯内存的Map数据结构里更新心跳时间;
两个重要属性
eureka.instance.lease-expiration-duration-in-seconds
leaseExpirationDurationInSeconds,表示eureka server至上一次收到client的心跳之后,等待下一次心跳的超时时间,在这个时间内若没收到下一次心跳,则将移除该instance,默认为90秒;
如果该值太大,则很可能将流量转发过去的时候,该instance已经不存活了。如果该值设置太小了,则instance则很可能因为临时的网络抖动而被摘除掉,该值至少应该大于leaseRenewalIntervalInSeconds;
eureka.instance.lease-renewal-interval-in-seconds
leaseRenewalIntervalInSeconds,表示eureka client发送心跳给server端的频率。如果在leaseExpirationDurationInSeconds后,server端没有收到client的心跳,则将摘除该instance。除此之外如果该instance实现了HealthCheckCallback,并决定让自己unavailable的话,则该instance也不会接收到流量,默认30秒;
Eureka Server端多级缓存机制
服务端注册表拉取维护
在拉取注册表的时候首先从ReadOnlyCacheMap里查缓存的注册表;若没有就找ReadWriteCacheMap里缓存的注册表;如果还没有,就从内存中获取实际的注册表数据。在注册表发生变更的时候会在内存中更新变更的注册表数据,同时过期掉ReadWriteCacheMap,此过程不会影响ReadOnlyCacheMap查询注册表;一段时间内(默认30秒),各服务拉取注册表会直接读ReadOnlyCacheMap;30秒过后,Eureka Server的后台线程发现ReadWriteCacheMap已经清空了,也会清空ReadOnlyCacheMap中的缓存;
多级缓存机制的优点
尽可能保证了内存注册表数据不会出现频繁的读写冲突问题;并且进一步保证对Eureka Server的大量请求,都是快速从纯内存走,性能极高;
客户端更新拉取维护
通过定时任务30秒拉取一次注册表,30秒发起一次心跳