注册中心原理剖析与设计实践
奈学
注册中心的作用及设计分析
1、什么是注册中心
服务注册中心:用来实现微服务实例的自动注册与发现,是分布式系统中的核心基础服务
在没有注册中心时:
需要全局的配置文件,各个模块各自维护,这种方式维护变更很不方便,导致改一个配置很多模块都要变更,导致相关风险;基于这种问题就可以基于注册中心
注册中心的主要功能:
服务注册、服务发现、健康检查、变更通知
- 服务注册:服务提供方将自身路由信息发布到注册中心,供消费方获取用于与提供方建立连接并发起调用
路由信息:注册服务节点IP、监听端口等路由信息
服务信息:序列化规则、路由规则、节点权重 - 服务发现:服务消费方通过访问注册中心获取服务提供方节点路由信息
启动拉取:服务消费方启动后就从注册中心拉取提供方节点列表、建立连接、进行RPC调用
通知回调:接受注册中心变更通知。重新获取数据,更新节点列表
轮训拉取:服务消费方运行过程中定时拉取服务提供方节点列表,用来更新本地数据 - 健康检查:确保已注册节点健康度,能够及时准确剔除失效节点,保证服务发现正确性
失效原因:部署重启、服务假死、异常终止
解决方案:上报心跳、服务探测
- 变更通知
当服务提供方节点发生变更时,注册中心应该能够第一时间把变更事件或变更后的数据推送到服务订阅方
订阅与通知:注册中心内为每个服务提供方建立订阅列表,当服务方节点变更时通知所有订阅该服务的消费方节点
2、注册中心设计
数据存储、超时处理 - 注册中心存储设计
数据组织:集群维度、节点维度
按照节点维度会使订阅服务难度加大,所有使用集群维度进行组织数据,消费方直接订阅整个集群的服务数据
订阅数组组织:也是使用集群维度进行数据存储
订阅方也需要按照订阅方集群维度维护服务提供方的集群服务信息,便于得知服务提供方的状态信息,在服务提供方有变更时便于通知订阅方
- 超时扫描
遍历扫描、动态分组
3、注册中心实现思考
自带存储,保证数据一致性
逻辑+配套存储- 节点变更通知
如何发送到指定节点
gossip协议
- gossip协议
Ø 六度分离理论
Ø 周期性散播消息
Ø 随机选择N个节点散播
Ø 散播不重复不回传
注册中心的作用
注册中心除了实现服务注册与发现,还可以用来实现服务治理相关功能
服务扩容/缩容、机器迁移、权重、灰度流量
- 节点变更通知
注册中心本质与设计思考
注册中心是什么
抛开应用,只是实现功能角度看,注册中心是什么
能存储核心数据,并提供服务订阅功能
存储系统主要关注点
- 数据可靠性数据冗余存储、确保不会因为单节点故障导致数据丢失
数据一致性 - 各个节点数据同步、保证数据一致性
服务可用性 - 多节点对等的对外提供服务
CAP定理
分布式系统中C(数据一致性), A(服务可用性), P(分区容错性)只能满足其二
P分区容错性,应用部署在不同网络分区,所以必须保证分区容错性使应用服务可用
- AP/CP选择
选择什么样的存储(CP或AP)作为注册中心,还需要从业务场景出发
注册中心集群内发现网络分区:是牺牲一致性继续提供服务还是待恢复数据一致性状态后再提供服务
CP or AP
作为注册中心的使用场景AP模型更适合
注册中心选型维度
注册中心选型如果只考虑CAP就过于片面了,还需要结合实际场景,多维度综合评估
Ø 数据模型 订阅
Ø 数据一致性
Ø 健康检查
Ø 性能与容量
Ø 稳定性
Ø 易用性
Ø 集群扩展性
Ø 成熟度
Ø 社区活跃程度
Zookeeper实现深入剖析
Zookeeper核心模块
节点角色:server节点组成的一个集群,在集群中存在唯一的leader节点负责响应写入请求,其他节点只负责接收转发Client请求
leader:响应写入请求,发起提案,超过半数Follower同意写入,写入成功
Follower:响应查询,将写入请求转发给leader,参与选举和写入投票
ObServer:响应查询。将写入请求转发给leader。不参与投票,只接收写入结果
peerType:participant or observer
- 选择逻辑
投票:获得法定数量的票数,超过集群节点数的半数 - 判断依据:
Epoch:leader的任期,每次当选任期都会递增
ZXID:Zookeeper事务ID。越大表示数据越新
SID:集群中每个节点的唯一编号
比较策略:任期大的胜出,任期相同的比较ZXID大的胜出,ZXID相同比较SID大的胜出
选主过程:
leader挂后,节点进入Looking状态,广播发起投票,选出“最大”发起二次投票,超过半数的为主节点leader
- Zab协议
Ø Zookeeper Atomic Broadcast
Ø Leader负责处理写入请求
Ø 两阶段提交
ZK数据一致性保障
Ø 创建出一个提案
Ø 提案放入待提交Map, key为ZXID
Ø 向所有Follow发送提案
Ø 判断提案是否已经提交
Ø 从待提交Map中取出提案
Ø 记录ACK
Ø 确保当前zxid之前没有待提交提案
Ø 统计ACK数量是否过半
Ø 提案顺序异常警告打印
Ø 提案可提交,从待提交Map中删除
Ø 通知Follower提交提案
Ø 将提案发送给ObServer
Zookeeper数据存储
树状结构存储数据,分为永久节点和临时节点
Ø DataNode
Ø DataTree
Ø ZKDataBase
-
DataNode
DataNode: Zookeeper中存储的最小单元,是持久化数据节点描述的最小单位
Ø DataNode parent; //父节点的引用
Ø byte data[]; //该节点存储数据
Ø Long acl; //acl控制权限
Ø StatPersisted stat; //持久化节点状态
Ø Set children; //子节点列表 -
DataTree
DataTree: 以树形结构存储了zookeeper中所有的数据信息
DataTree
Ø ConcurrentHashMap<String, DataNode> nodes;
Ø WatchManager dataWatches; //数据变更通知
Ø WatchManager childWatches; //节点变更通知
Ø String rootZookeeper; //根节点
Ø Map<Long, HashSet> ephemerals //临时节点信息
nodes Key: path, Value DataNode
ephemerals Key: session, Value: path的集合
HashMap<String, HashSet> watchTable
HashMap<Watcher, HashSet> watch2Paths -
ZKDataBase
ZKDataBase: 负责管理Zookeeper的数据、 会话信息和事务日志
ZKDataBase
DataTree dataTree;
ConcurrentHashMap<Long, Integer> sessionsWithTimeouts; //客户端会话连接管理
FileTxnSnapLog snapLog; //事务日志
Zookeeper&注册中心
Ø 服务注册:创建临时Node
Ø 服务发现:查询Node节点数据
Ø 健康检查:临时节点,检查临时节点是否存在,从而得知服务是否下线
Ø 信息订阅: Watch机制,可以通知服务变更信息
Ø 服务注册
l Zookeeper顺序一致性,不保证读到最新数据
l 选举过程中不可用
Ø 服务发现
l Zookeeper顺序一致性,不保证读到最新数据
l 选举过程中不可用
注册中心扩展功能
服务治理功能
下发管控命令:动态权重、流量路由、服务熔断降级、权限管理、动态过载保护策略、AB测试
- 灰度上线
先发布少量节点验证、降低对线上业务的影响
步骤:降低权重、发布服务、观察业务、全量发布 - 服务熔断
当某个服务提供方异常不可用时,或实际情况下需要暂停某些业务,有损提供服务,可以通过注册中心下发熔断指令