一、服务注册发现简要流程

首先通过以下一幅图简单看下eureka的服务注册发现流程是什么样的:

1、服务提供者提供应用服务,注册到eureka server中。

2、服务消费者每30秒去去注册中心拉取服务的ip,端口,接口地址等信息。

3、服务消费者拉取到服务提供者的应用信息后,可以直接去调用服务提供者的接口。

二、服务发现注册的整体流程

三、主要概念及原理

服务注册

服务注册的原理主要涉及到eureka server的存储结构,采用一个三层缓存的结构。具体内部的实现逻辑参考二中的图。

层级 名称 实现方式 更新方式 数据变更
第一层 readOnlyCacheMap(只读) ConcurrentHashMap 定时更新(默认30s) 定时拉取readWriteCacheMap
第二层 readWriteCacheMap(读写) guava 实时更新 guava的load机制
第三层 register(注册表) 双层ConcurrentHashMap 实时更新 客户端的注册、续约、下线

服务续约

当服务提供者完成服务信息注册后,会维持一个心跳,定时向eureka server 发送rest请求,告诉其还活着。默认心跳间隔30s。

服务获取

eureka client会定期(默认30s)向eureka server获取获取注册的服务信息,这个获取分为全量获取增量获取

默认配置下,当客户端首次启动后,会向服务端发起一次全量获取并缓存本地信息,之后每隔30s发起一次增量获取,更新本地缓存。

服务调用

通常服务间调用使用组件feign,发起rest请求;

其内集成了ribbon,ribbon默认使用了轮询的负载策略,会将eureka client拉取的注册信息拉取到自己这,实现负载。

服务下线

表示要从注册中心删除该服务的注册信息,使该服务不能被调用。

服务下线的方式:

方式 实现 效果
直接停服务 直接kill服务 90s内注册中心检测到服务无续约,才删除,无法立即下线
通过注册中心接口强制下线 向eureka 注册中心发送delete 默认30s的心跳机制,如果在这段时间没有停掉服务,那么会让该服务再次上线
客户端主动下线 @GetMapping("/offline")
public void offline(){
DiscoveryManager.getInstance().shutdownComponent();
}
优雅的下线服务

失效剔除

在eureka server中有一个定时任务Evict,该任务默认每60s执行一次,其作用域在readWriteCacheMap和register上。

当有服务提供者在默认90s时间内,没有进行服务续约,当Evict执行时,会对这样失效的注册信息进行剔除。通常是宕机的服务或者强制kill的服务。

自我保护

官方定义:自我保护模式正是一种针对网络异常波动的安全保护措施,使用自我保护模式能使Eureka集群更加的健壮、稳定的运行。

Eureka Server在运行期间会统计心跳失败的比例在15分钟内是否低于85%,如果出现低于的情况,Eureka Server会将当前的实例注册信息保护起来,不会让它们立刻过期。

此配置在默认环境下开启。

自我保护存在的问题:在保护期间,服务挂掉,导致服务无法下线,造成调用接口失败。

eureka宕机后,服务之间仍然可以通信。

因为eureka client本地缓存注册表信息,当eureka server宕机后服务间仍然可以访问,但是服务提供端和服务消费端又分为以下情况:

  • 当服务消费端重启后,本地缓存失效,与服务提供端的映射不存在了,无法进行服务调用。
  • 当服务提供端重启后,在服务调用端的本地缓存中,仍然保存有在eureka宕机前的缓存信息,可以正常调用服务。

集群注册信息同步

  • eureka采用的同步方式是peer to peer(对等复制),副本间不分主从,任何副本都可以接收写操作,然后每个副本间互相进行数据更新。

  • Eureka Server 本身依赖了 Eureka Client,也就是每个 Eureka Server 是作为其他 Eureka Server 的 Client。

  • Eureka Server 启动后,会通过 Eureka Client 请求其他 Eureka Server 节点中的一个节点,获取注册的服务信息,然后复制到其他 peer 节点。

  • Eureka Server 每当自己的信息变更后,例如 Client 向自己发起注册、续约、注销请求, 就会把自己的最新信息通知给其他 Eureka Server,保持数据同步。

  • 存在的问题:

    • (1)每个节点都可以进行写操作,会导致数据冲突。

    • (2)如果自己的信息变更是另一个Eureka Server同步过来的,这是再同步回去的话就出现数据同步死循环了。

  • 问题(1)解决方案:

    Eureka 是通过 lastDirtyTimestamp 这个类似版本号的属性来解决该问题。 lastDirtyTimestamp 是注册中心里面服务实例的一个属性,表示此服务实例最近一次变更时间。

  • 问题(2)解决方案:

    Eureka Server 在执行复制操作的时候,使用 HEADER_REPLICATION 这个 http header 来区分普通应用实例的正常请求,说明这是一个复制请求,这样其他 peer 节点收到请求时,就不会再对其进行复制操作,从而避免死循环。

eureka保证CAP中的AP

通过前面了解到,eureka并没有保证数据的强一致性,只保证了数据的最终一致性,通过集群模式保证了高可用
原文链接:https://juejin.cn/post/7057699861868576799