欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  移动技术

【华为云专家原创】 服务注册与发现如何满足服务治理?

程序员文章站 2022-06-19 10:21:36
教授提出,分别指 Consistency (一致性)、Availablity (可用性)、Partition tolerance (分区容忍性)。Eric Brewer 认为,以上三个指标最多同时满足两个。Consistency,指数据一致性,表示一个系统的数据信息(包括备份数据)在同一时刻都是一致的。在分布式系统下,同一份数据可能存在于多个不同的实例中,在数据强一致性的要求下,对其中一份数据的修改必须同步到它的所有备份中。在数据同步的任何时候,都需要保证所有对该份数据的请求将返回同样的状态。Ava...
摘要:本文主要介绍了服务注册与发现的原理,以及常用的几种服务注册与发现组件介绍对比。

在单体应用向微服务架构演进的过程中,原本的巨石型应用会按照业务需求被拆分成多个微服务,每个服务提供特定的功能,并可能依赖于其他的微服务。每个微服务实例都可以动态部署,服务实例之间的调用通过轻量级的远程调用方式(HTTP、消息队列等)实现,它们之间通过预先定义好的接口进行访问。

由于服务实例是动态部署,每个服务实例的地址和服务信息都可能动态变化,势必需要一个中心化的组件对各个服务实例的信息进行管理,该组件管理了各个部署好的服务实例元数据,包括不仅限于服务名、IP 地址、端口号、服务描述和服务状态等。

什么是服务注册与发现?

服务注册与发现主要包含两部分:服务注册与服务发现。服务注册是指服务实例启动时将自身信息注册到服务注册与发现中心,并在运行时通过心跳等方式向服务注册与发现中心汇报自身服务状态;服务发现是指服务实例向服务注册与发现中心获取其他服务实例信息,用于进行接下来的远程调用。接下来让我们介绍服务注册与发现中心的职责和服务实例进行服务注册的基本流程,以及分布式系统中数据同步的基本原理 CAP。

服务注册与发现中心有什么功能?

在传统单体应用中,应用都是部署在固定的物理机器或者云平台上,他们之间的调用一般是通过固定在代码内部或者配置文件的服务地址和端口直接发起。由于应用数量较少,系统结构复杂度不高,开发人员和运维人员可以较为轻松地进行管理和配置。

随着应用架构向微服务架构迁移,服务数量的增加和动态部署动态扩展的特性,使得服务地址和端口在运行时是随时可变的。对此,我们需要一个额外的中心化组件统一管理动态部署的微服务应用的服务实例元数据,一般称它为服务注册与发现中心。服务注册与发现中心主要有以下的职责:

  • 管理当前注册到服务注册与发现中心的微服务实例元数据信息,包括服务实例的 服务名、IP 地址、端口号、服务描述和服务状态等;
  • 与注册到服务发现与注册中心的微服务实例维持心跳,定期检查注册表中的服务实例是否在线,并剔除无效服务实例信息;
  • 提供服务发现能力,为服务调用方提供服务提供方的服务实例元数据。

通过服务发现与注册中心,可以很方便地管理系统中动态变化的服务实例信息。与此同时,它也可能成为系统的瓶颈和故障点。因为服务之间的调用信息来自于服务注册与发现中心,当它不可用时,服务之间的调用可能无法正常进行。因此服务发现与注册中心一般会集群化部署,提供高可用性和高稳定性。

分布式中的 CAP 理论

在本质上来讲,微服务应用属于分布式系统的一种落地实践,而分布式系统最大的难点是处理各个节点之间数据状态的一致性。即使是倡导无状态的 HTTP RESTful API 请求,在处理多服务实例情况下的修改数据状态请求,也是需要通过数据库或者分布式缓存等外部系统维护数据的一致性。CAP 原理是描述分布式系统下节点数据同步的基本定理。

CAP 原理由加州大学的 Eric Brewer 教授提出,分别指 Consistency (一致性)、Availablity (可用性)、Partition tolerance (分区容忍性)。Eric Brewer 认为,以上三个指标最多同时满足两个。

  • Consistency,指数据一致性,表示一个系统的数据信息(包括备份数据)在同一时刻都是一致的。在分布式系统下,同一份数据可能存在于多个不同的实例中,在数据强一致性的要求下,对其中一份数据的修改必须同步到它的所有备份中。在数据同步的任何时候,都需要保证所有对该份数据的请求将返回同样的状态。
  • Availablity,指服务可用性,要求服务在接受到客户端请求后,都能够给出响应。服务可用性考量的是系统的可用性,要求系统在高并发情况下和部分节点宕机的情况下,系统整体依然能够响应客户端的请求。
  • Partition tolerance,指分区容忍性。在分布式系统中,不同节点之间是通过网络进行通信。基于网络的不可靠性,位于不同网络分区的服务节点可能会通信失败,如果系统能够容忍这种情况,说明它是满足分区容忍性的。如果系统不能够满足分区容忍性,那么将会限制分布式系统的扩展性,即服务节点的部署数量和地区都会受限,违背了分布式系统设计的初衷,所以一般来讲分布式系统都会满足分区容忍性。

在满足了分区容忍性的前提下,分布式系统并不能同时满足数据一致性和服务可用性。假设服务A现在有两个实例A1和A2,它们之间的网络通信出现了异常,基于分区容忍性,这并不会影响A1和A2独立的正常运行。假如此时客户端请求A1,请求将数据B从B1状态修改为B2,由于网络的不可用,数据B的修改并不能通知到实例A2。如果此时另一个客户端向A2请求数据B,如果A2返回数据B1,将满足服务可用性,但并不能满足数据一致性;如果A2需要等待A1的通知之后才能够返回数据B的正确状态,虽然满足了数据一致性,但并不能响应客户端请求,违背了服务可用性的指标。

基于分布式系统的基本特质,P 是必须要满足,接下来需要考虑满足 C 还是 A。在类似银行之类对金额数据要求强一致性的系统中,要优先考虑满足数据一致性;而类似大众网页之类的系统,用户对网页版本的新旧不会有特别的要求,在这种场景下服务可用性高于数据一致性。

如何选择服务注册与发现框架?

随着近几年微服务框架高速发展,目前业界已经开源出了大量优秀的服务注册与发现组件,包括不仅限于 Consul、Etcd、Zookeeper、Eureka。它们之间各有千秋,在组件选型时可以根据自身业务的需要进行选择和改造,接下来我们主要对 Consul、Etcd、Zookeeper 作一些简单的介绍和比较。

基于 Raft 算法、开箱即用的服务发现系统 Consul

Consul 由 HashiCorp 开源,是支持多个平台的分布式高可用系统。Consul 使用 Golang 语言实现,主要用于实现分布式系统的服务发现与配置,满足 AP 特性。Consul 是分布式、高可用和可横向扩展的,提供以下主要特性:

  • 服务发现:可以使用 HTTP 或者 DNS 的方式将服务实例的元数据注册到 Consul,和通过 Consul 发现所依赖服务的元数据列表。
  • 检查检查:Consul 提供定时的健康检查机制,定时请求注册到 Consul 中的服务实例提供的健康检查接口,将异常返回的服务实例标记为不健康。
  • Key/Value:Consul 提供了 Key/Value 存储功能,可以通过简单的 HTTP 接口进行使用。
  • 多数据中心:Consul 使用 Raft算法来保证数据一致性,提供了开箱即用的多数据中心功能。

服务实例与 Consul 的交互如下图所示:

【华为云专家原创】 服务注册与发现如何满足服务治理?

Consul 与服务实例的交互过程

通过 Consul 实现服务注册与发现中心的调用过程如下:

  1. Producer在启动之初会通过 /register 接口将自己的服务实例元数据注册到 Consul 中;
  2. Consul 通过 Producer 提供的健康检查接口 /health 定时检查 Producer 的服务实例状态;
  3. Consumer 请求 Consul 的接口获取 Producer 服务的元数据;
  4. Consumer 从 Consul 中返回的 Producer 服务实例元数据列表中选择合适的服务实例,使用其配置的 IP 和端口信息发起服务调用,如图 7-1 中 Consumer 调用 Producer 的 /service 接口。

Consul 是一个高可用的分布式系统,支持多数据中心部署。一个 Consul 集群由多个部署和运行了 Consul Agent 的节点组成。Consul 集群中存在两种角色,Server 和 Client。每个 Consul Agent 负责对本地的服务进行监控检查,并将查询请求转发到 Server 中进行处理。Consul 简单的架构图如下图所示:

【华为云专家原创】 服务注册与发现如何满足服务治理?

Consul 架构图

从上图可知,Consul 主要由 Consul Client 和 Consul Server 组成,且 Consul 使用 Gossip 协议来管理成员和广播消息到集群。

Consul 作为一个开箱即用、高可用分布式服务发现和配置系统,可以很方便地为微服务的服务治理提供强有力的支持。在后面的课时中,我们将实现一个 Consul 的客户端,将我们自身的 Web 服务注册到 Consul 中,以供其他服务或者网关调用。

基于 HTTP 协议的分布式 key/Value 存储系统 Etcd

Etcd 是由 CoreOS 开源,采用 Golang 语言编写的分布式、高可用的 Key/Value 存储系统,主要用于服务发现和配置共享。Ectd 的经典应用场景有:

  • Key/Value 存储:Etcd 支持 HTTP RESTful API,提供强一致性、高可用的数据存储能力。
  • 服务发现:通过在 Etcd 中注册某个服务的目录,服务实例连接 Etcd 并在目录下发布对应 IP 和 Port 以供调用方使用,可以有效实现服务注册与发现的功能;
  • 消息发布与订阅:通过 Etcd 的 Watcher 机制,可以使订阅者订阅他们关心的目录。当消息发布者修改被监控的目录内容时,可以将变化实时通知给订阅者。

【华为云专家原创】 服务注册与发现如何满足服务治理?

Etcd 的集群的基本架构图

相对于其他的组件来讲,Etcd 更为轻量级,部署简单,支持 HTTP 接口。它可以为服务发现提供一个稳定高可用的消息注册仓库,为微服务协同工作提供了有力的支持。

重量级一致性服务系统 Zookeeper

Zookeeper 作为 Hadoop 和 Hbase 的重要组件,是一个开源的分布式应用协调服务,目前由 Apache 基金会维护,采用 Java 语言开发。Zookeeper 致力于为分布式应用提供一致性服务,它的设计目标是将分布式系统中那些复杂且容易出错的服务封装为简单高效的接口以供开发人员使用。

Zookeeper 底层只提供了两个功能,管理客户端提交的数据和为客户端程序提供数据节点的监听服务。它是一个典型的分布式数据一致性解决方案,基于 ZooKeeper 可以实现服务发现与注册、消息发布与订阅、分布式协调与通知、分布式锁、Master 选举、集群管理和分布式队列等诸多功能。

Zookeeper 集群中存在三种角色,分别为 Leader、Follower 和 Observer,架构图如图所示:

【华为云专家原创】 服务注册与发现如何满足服务治理?

Zookeeper 架构图

Zookeeper 通过 ZAB 协议来保证其数据一致性。ZAB 不是一种通用的分布式一致性算法,它是在 Paxos 算法的基础上,为 Zookeeper 特别设计的崩溃可恢复的原子消息广播协议。ZAB 协议主要包含两种基本模式,崩溃恢复和消息广播:

  • 崩溃恢复模式:在服务启动或者 Leader 服务器崩溃时,ZAB协议就会进入崩溃恢复模式,在所有的 Follower 中选举出 Leader。当选举了新的 Leader 后,集群中有半数与新的Leader 完成状态同步后就会退出恢复模式,进入到消息广播模式。
  • 消息广播模式:ZAB协议消息广播过程使用的是一个原子广播协议,类似于一个二阶段提交,但是又有所不同,并非所有 Follower 节点都返回 Ack 才进行一致性事务完成,而是只需要半数以上即可提交完成一个事务广播。

Zookeeper 为分布式系统提供协调服务,能够有效地支持微服务架构的服务注册和发现机制。同时 Zookeeper 中提供的其他数据一致性解决方案,能够有力支撑微服务中分布式业务的开发。

服务注册与发现组件的对比

以上介绍的三种服务注册与发现组件在业界都已经有了广泛的应用,在很多大公司的项目中都能看到它们的身影,比如 Zookeeper 在 Hadoop 体系中发挥了极其重要的分布式协调作用。下面将从特性方面比较他们的异同:

【华为云专家原创】 服务注册与发现如何满足服务治理?

从软件的生态出发,Consul 是以服务发现和配置作为主要功能目标,附带提供了 Key/Value 存储,相对于 Etcd 和 Zookeeper 来讲业务范围较小,更适合于服务注册与发现。Etcd 和 Zookeeper 属于通用的分布式一致性存储系统,被应用于分布式系统的协调工作中,使用范围抽象,具体的业务场景需要开发人员自主实现,如服务发现、分布式锁等。Zookeeper 具备广大的周边生态,在分布式系统中得到了广泛的使用;而 Etcd 以简单易用的特性吸引了大量开发人员,在目前火热的 Kubernetes 中也有应用。仅从服务注册与发现组件的需求来看,选择 Consul 作为服务注册与发现中心能够取得更好的效果;如果系统存在其他分布式一致性协作需求,选择 Etcd 和 Zookeeper 反而能够提供更多的服务支持。

小结

本文主要介绍了服务注册与发现的原理,以及常用的几种服务注册与发现组件介绍对比。服务注册与发现在微服务架构中是各个微服务之间的协调者,因此掌握服务注册与发现的基本原理,正确使用服务注册与发现组件是非常重要的一件事。在接下来的文章中,我们将基于 Consul 实现 Go 微服务的服务注册与发现。

本文分享自华为云社区《【华为云专家原创】 服务注册与发现如何满足服务治理?》,原文作者:aoho 。

 

点击关注,第一时间了解华为云新鲜技术~

本文地址:https://blog.csdn.net/devcloud/article/details/111946430