一、服务注册发现简要流程
首先通过以下一幅图简单看下eureka的服务注册发现流程是什么样的:
![](https://img.haomeiwen.com/i16830368/06a0e04b3bd14ed2.png)
1、服务提供者提供应用服务,注册到eureka server中。
2、服务消费者每30秒去去注册中心拉取服务的ip,端口,接口地址等信息。
3、服务消费者拉取到服务提供者的应用信息后,可以直接去调用服务提供者的接口。
二、服务发现注册的整体流程
![](https://img.haomeiwen.com/i16830368/bfc95ffd152d17e9.png)
三、主要概念及原理
服务注册
服务注册的原理主要涉及到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拉取的注册信息拉取到自己这,实现负载。
关于feign和ribbon会在后续学习中具体讲解。
服务下线
表示要从注册中心删除该服务的注册信息,使该服务不能被调用。
服务下线的方式:
方式 | 实现 | 效果 |
---|---|---|
直接停服务 | 直接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宕机前的缓存信息,可以正常调用服务。
集群注册信息同步
参考:https://blog.csdn.net/fox_bert/article/details/104210074
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并没有保证数据的强一致性,只保证了数据的最终一致性,通过集群模式保证了高可用。
网友评论