背景/Background
比较老的注册中心大部分使用ZooKeeper来实现, 但是由于ZooKeeper为CP系统,无法保证分布式下的可用性,需要使用AP系统
根据 Netflix Eureka 开发并优化出go版本服务注册发现系统Discovery,与caster深度结合 ,客户端使用HTTP协议与注册中心交互。
相关文档/Reference
Eureka文档:https://github.com/Netflix/eureka/wiki
设计目标/Design Goals
业务目标:
1,实现AP系统服务注册发现,保证数据最终一致性(非强一致性,勿要将 discovery 用作协调器)。
2,与平台深度结合,基于k8s pod实现滚动发布,蓝绿发布。
3,网络闪断时服务可开启自我保护,保证健康的服务可用
4,实现各个语言sdk,基于HTTP协议保证交互简易。
性能指标:
1,注册数据的分布式最终一致性
2,renew接口 QPS 20k ,其他接口QPS 10k下可用
概览/Overview
基本流程
通过appid(服务名)和Addr(IP:Port)定位实例
Provider 注册后定期(30s)心跳一次,注册, 心跳,下线都需要进行同步,注册和下线需要进行长轮询推送
Consumer 启动时拉取实例,发起30s长轮询
Server 定期(60s) 检测失效(90s)的实例,失效则剔除。短时间里丢失了大量的心跳连接(15分钟内心跳低于期望值*85%),开启自我保护,保留服务不过期。
重要步骤
1.心跳的复制(Peer to Peer)检查数据一致性(网络抖动或分区导致数据不一致):
注册时根据当前时间生成dirtyTime, A向B同步实例心跳时:
返回-404 表示 (1)B中不存在实例 (2)B中dirtyTime较小 A携带自身dirtyTime向B发起注册请求,把最新信息同步过去。
返回-409 表示 (1)B中dirtyTime较大 不同意采纳A的信息而是将自身实例的信息放在消息体里返回B更新本地
2.网络分区时的自我保护
当网络分区发生时,每个Discovery节点,会持续的对外提供服务,接收该分区下新实例的服务注册和发现。
短时间丢失大量心跳,进入自我保护,保证健康的实例不被剔除,同时保留”好数据“与”坏数据“
自我保护:每分钟的心跳数小于阈值(实例数量285%),每15分钟重置心跳阈值
非自我保护下,随机分批逐次剔除,尽量避免单个应用被全部过期。
3.客户端
长轮询+服务端推送变化,让服务发现的实时性更高
订阅式客户端,推送客户端关注的实例变化
Eureka客户端缓存,即便所有的都失效,依旧可以调用服务
多注册中心
1.同一个机房内部,discovery节点通过广播进行注册信息同步。
2.跨机房注册信息同步时,discovery节点会将信息推送到其他的机房slb,再由slb通过负载均衡把信息推送到机房内部节点。机房内部在进行广播同步。
- 注意: 跨机房同步时,注册信息为单向同步,slb收到信息后LB到机房内部节点,内部节点只在内部广播,不会推送到其他slb。