写点什么

技术分享| 分布式系统中服务注册发现组件的原理及比较

作者:anyRTC开发者
  • 2022 年 9 月 20 日
    上海
  • 本文字数:2632 字

    阅读完需:约 9 分钟

背景

在分布式架构的系统中,服务发现简单来讲就是通过服务名找到提供服务的实例地址和端口,主要用于解决如何获取服务实例地址问题。


随着容器技术的兴起,服务集群部署在系统各处,服务之间的远程调用都需要通过服务发现来实现。服务注册发现是分布式系统中不可或缺的关键组件,常用于构建服务注册发现解决方案的开源框架如 ZooKeeper、Etcd、Consul。下面主要介绍一下如何基于 ZooKeeper、Etcd、Consul 构建服务注册发现方案并进行一下对比。


一个标准的服务注册发现架构主要有三部分组成,分别是服务注册中心、服务消费者、服务提供者,架构图如下所示:



服务注册中心是服务发现的核心组件,其本质上是一个服务名和服务实例地址映射集合,除了提供服务注册发现,服务记录,动态管理服务等功能外,还需要具备如下能力:


  • 容错(Fault Tolerance):服务注册中心保存了分布式系统中所有服务名与服务实例地址映射,一旦故障必将导致整个系统不可用,是整个分布式系统核心,必须具备高可用性。

  • 服务健康检查(Service Health Check):服务注册中心必须要能及时发现故障实例并将其注销以防止被错误访问。

  • 监视器(Watcher):服务注册中心必须具备及时通知服务调用者服务实例注册或注销的能力,以便服务调用者及时采取措施。


注册/注销服务实例一般有两种选择:


  1. 服务实例自己注册即 Self-Registration 模式,在服务实例启动成功后主动将自己注册到服务注册中心,这种方法好处是架构简单但需要为服务用到的每种编程语言实现注册代码;

  2. 通过其他组件来注册服务实例即 Thrid-party Registration 模式,例如使用一个独立 Agent 通过轮询或监听事件去跟踪运行的服务实例变化进行注册或注销,好处是服务实例与服务注册中心解耦但引入第三方组件增加了架构复杂性。

服务注册发现组件方案

ZooKeeper

ZooKeeper 提供分布式协调服务,在分布式系统中常被用于配置管理、名字服务、分布式锁及组管理,通常运行在一组节点上实现容错(当运行在 n 个节点上时能容忍 n/2 个节点同时故障)。


如何通过 ZooKeeper 来实现服务发现?

ZooKeeper 使用临时节点(ephemeral node)来实现服务注册和基本的健康检查功能。每当服务实例启动就会在 ZooKeeper 中注册一个临时节点,而当服务实例故障或下线该临时节点会被 ZooKeeper 自动删除,如果有其他服务依赖这个服务可以设置监听该服务实例对应的临时节点,当临时节点被删除时,依赖该服务的其他服务会获得通知。依赖 ZooKeeper 自身的高可用及临时节点提供的健康检查和监听机制来实现具备容错能力的服务发现机制。

组件特点


从 ZooKeeper 的数据结构特点看,并不是基于服务注册而设计的,ZooKeeper 提供的命名空间与文件系统的名称空间非常相似,在数据结构上高度抽象为 K-V 格式,十分通用。


ZooKeeper 组件支持节点短暂存在,只要创建 znode 的会话处于活动状态,这些 znode 就会存在,会话结束时,将删除 znode。Dubbo 框架正是基于这个特点,服务启动往 Zookeeper 注册的就是临时节点,需要定时发心跳到 ZooKeeper 来续约节点,并允许服务下线时,将 ZooKeeper 上相应的节点删除,同时 ZooKeeper 使用 ZAB 协议虽然保证了数据的强一致性。


实际开发过程中,建议使用 Apache Curator 来替代 Zookeeper 原生客户端库,Apache Curator 通过封装 ZooKeeper 原生 API,提供更高抽象层次 API 让 ZooKeeper 使用起来更加容易和可靠,而且提供专用于实现服务发现的 API。

Etcd

Etcd 是一个基于 Raft 共识算法具备线性强一致性(linearizable)的 Key-Value 存储系统,可以为每个 Key 设置 TTL(time to live),当 TTL 过后相应 Key 会自动过期失效。


基于 Etcd 构建服务发现解决方案将 Etcd 作为服务注册中心,服务实例注册就是在 Etcd 中构建一个 Key-Value 记录,由服务实例自身或代理负责设置并定期更新其关联 Key 的 TTL,如果服务实例故障其对应 Key 就会在 TTL 之后过期失效,相当于将该故障服务实例注销,通过定时心跳以达到监控健康状态的效果。而且 Etcd 提供监听机制,允许为 Key 设置监听器当该 Key 发生变化时,监听器能及时获取通知。


Etcd 自身的高可用特性,基于 TTL 提供基本的服务健康检查,基于监听机制及时感知服务实例变化,使 Etcd 成为微服务架构中常用服务发现解决方案。


Consul

Consul 是一个成熟的服务发现解决方案。其核心是一个基于 Raft 共识算法具备线性强一致性的 Key-Value 存储系统作为服务注册中心,并提供代理(Agent)机制一方面用于协调服务注册,一方面提供服务健康检查。代理(Agent)会在每个运行服务的节点上启动,获取节点地址并将该服务实例注册到服务注册中心。


架构上 Consul 包括两类组件:Server、Agent,服务注册信息保存在 Server 上,通过 Raft 共识算法保证多个 Server 间数据线性强一致,保证服务注册中心高可用;将所有 Agent 作为集群节点,使用 Gossip 协议进行组关系管理和故障探测,当有 Agent 加入(启动)或离开(故障)集群时其他 Agent 会得到通知,实现服务健康检查和监视功能。


Gossip 协议常用于集群组关系管理和故障检测,每个节点都通过一个或多个引导节点加入集群,引导节点有集群中所有节点列表,每个节点都从自己所知节点列表中随机选择一组节点周期性地发送多播消息,最终集群中所有节点都能知道其他节点。这个过程看起来很神奇,实际上 Gossip 协议能在几秒内将消息传遍有上百节点的集群。Akka、Riak、Cassandra 都使用 Gossip 协议维护集群成员列表和故障探测。


总结

文章总结了分布式系统中常用的服务注册发现解决方案,基于 Zookeeper、Etcd、Consul 框架方案核心思想是通过一组实例(3 个或者 5 个)提供线性强一致性(Linearizable)分布式高可用 Key-Value 存储服务,将 Key-Value 存储作为服务注册中心,当相关 Key 发生变化时监视器能及时通知客户端,通知机制配合服务健康检查当有服务实例启动或故障时客户端能及时感知服务拓扑变化以实现智能路由,从实现方式上看它们可以看作是中心化的服务发现方案。


总体比较,Consul 提供了原生的分布式锁、健康检查、服务发现机制支持,让业务可以更省心,同时也对多数据中心进行了支持;当然 Etcd 和 ZooKeeper 也都有相应的库,也能很好的进行支持,但是这两者不支持多数据中心;


ZooKeeper 在 Java 业务中选型使用的较多,Etcd 因为是 go 语言开发的,所以如果本身就是 go 的技术栈,使用这个也是个不错的选择,Consul 在国外应用比较多,中文文档及实践案例相比 etcd 较少。


此外 Consul 和 Etcd 都非常适合容器环境,因为 Docker 容器启动、停止都会发送事件(Event),基于事件通知机制非常便于将服务实例从 Consul 或 Etcd 上注册、注销。


参考文档


服务发现框架选型: Consul、Zookeeper还是etcd ?



发布于: 刚刚阅读数: 6
用户头像

实时交互,万物互联! 2020.08.10 加入

实时交互,万物互联,全球实时互动云服务商领跑者!

评论

发布
暂无评论
技术分享| 分布式系统中服务注册发现组件的原理及比较_音视频_anyRTC开发者_InfoQ写作社区