编辑
2025-09-22
课外知识
00

目录

服务发现
服务发现
注册模式
发现模式
分布式理论
一致性
CAP 定理
BASE 理论
分布式共识算法
Paxos 算法
Raft 算法
Gossip 协议
服务发现方案
DNS
mDNS
Zookeeper
Etcd
Consul
Nacos
参考

微服务在大型项目开发过程中已经非常普遍,而在通过 RPC 调用微服务时,首要问题是如何获取服务实例的地址。最简单的方式是静态配置,也就是将服务地址写入配置文件中。然而,现代微服务体系中,大部分服务都是动态上线的,在部署之前往往并不知道其确切地址;同时,服务实例的地址也可能因为扩缩容、故障转移等原因而频繁变化。若依赖静态配置,不仅维护成本高,还容易导致调用失败。

为了解决这一问题,我们需要一个专门的组件:服务注册中心。它的职责是动态管理和维护服务提供者的地址信息,并将这些信息提供给服务调用者,从而实现自动化、可扩展的服务寻址机制。

image.png

服务发现

服务发现

即服务调用者能够自动获取服务提供者地址列表的能力,是微服务架构的灵魂。如上图所示(示意图来自:分布式系统之服务发现(Service Discovery)),一个完整的服务发现架构主要包含三个部分:服务注册中心服务调用者服务提供者。其中,服务注册中心是核心组件,本质上可以看作是一个“服务名服务->实例地址”的映射集合(有点类似 DNS 的功能)。

注册模式

当一个新的服务实例启动时,它需要将自己的元信息(例如服务名、IP 地址、端口、健康状态等)注册到服务注册中心。注册的方式有两种:

  • 自注册(Self-Registration):服务实例自己向注册中心发起注册和注销操作。优点是实现简单,缺点是耦合度高,服务本身需要关心注册逻辑。
  • 第三方注册(Third-Party Registration):由独立的代理或 Sidecar 组件负责将服务实例的信息注册到注册中心,应用无需关心注册细节。这样可以降低服务和注册中心的耦合度,但增加了运维复杂度。

发现模式

当服务调用者需要访问某个服务时,就涉及到“如何获取服务地址”的问题,这就是服务发现的模式。如图所示,主要分为两类(示意图来自:服务发现-从原理到实现):

  • 客户端发现(Client-Side Discovery):由服务调用方直接向注册中心查询可用服务实例,并在本地进行负载均衡。优点是调用灵活、无需额外代理;缺点是客户端逻辑较复杂,且需要与注册中心紧密耦合。

image.png

  • 服务端发现(Server-Side Discovery):服务调用方只需向一个固定的负载均衡入口发起请求,由该组件负责向注册中心查询实例并转发请求。Kubernetes Service、Envoy + Istio 等就是这一模式的代表。优点是调用方简单,缺点是需要额外的代理层。

image.png

分布式理论

在理想情况下,服务注册中心只需要一个节点就能完成所有的注册与发现工作。但在实际生产环境中,单节点的注册中心存在明显缺陷

  • 单点故障:一旦节点宕机,整个服务发现体系都会瘫痪,服务调用无法正常进行。
  • 扩展性差:随着微服务数量和请求规模的增长,单节点难以承担高并发的注册与查询压力。
  • 可靠性不足:即便节点短时间内恢复,也可能导致部分服务注册信息丢失或不一致。

为了提升可靠性和可用性,服务注册中心往往采用多节点集群部署。但一旦进入集群化场景,新的挑战随之而来:如何保证多节点之间的数据一致?如何在网络分区时保证系统的可用性?要理解服务注册中心如何保证可用性和一致性,就需要引入分布式系统的一些基本理论。

一致性

这里讨论的一致性概念,不同于 CPU 缓存一致性(Cache Coherence),也不同于传统数据库 ACID 中的一致性(Consistency)。 在分布式系统中,一致性主要指多个节点在面对读写操作时对数据状态达成的共识。也就是说,无论客户端访问哪一个节点,都应该得到符合一致性模型的结果。

  • 在 CAP 定理 中,一致性(C)通常对应线性一致性(Linearizability),要求操作完成后,所有节点必须立刻看到最新值。
  • 在实际分布式服务注册中心和缓存系统中,为了兼顾可用性,也常采用最终一致性(Eventual Consistency)的策略,即允许短暂的不一致,但经过一段时间后系统会收敛到一致状态。

常见的一致性模型包括:

  • 线性一致性(Linearizability Consistency):最严格的强一致性模型,要求操作一旦完成,所有节点必须立即看到最新状态,并且操作顺序与实际发生时间一致。
  • 顺序一致性(Sequential Consistency):要求操作在全局有一个顺序,且各线程内部顺序保持一致,但不要求严格按照操作发生的真实时间。
  • 因果一致性(Causal Consistency):保证因果相关的操作按顺序执行,但对不相关的操作顺序不作要求。
  • 最终一致性(Eventual Consistency):允许短时间内出现不一致,但系统会在一段时间后自动收敛到一致状态,常用于高可用性优先的场景。

CAP 定理

一致性(Consistency)、可用性(Availability)和分区容忍性(Partition Tolerance)三者不可同时满足。对于一个分布式系统来说,网络分区(Partition)是不可避免的,因此在出现分区时,系统必须在一致性(C)和可用性(A)之间做取舍。

需要注意的是,CAP 并不是“随意选择两个”,而是因为 P 是前提条件,一旦发生分区,系统要么保证 CP(牺牲可用性来保证一致性),要么保证 AP(牺牲一致性来保证可用性)。在网络正常、没有分区的情况下,C 和 A 是可以同时满足的。

BASE 理论

与强调强一致性的 ACID 不同,BASE 是分布式系统领域的一种实践性理论,其核心思想是:在大规模分布式环境下,为了保证高可用和可扩展性,可以容忍一定程度的“暂时不一致”。BASE 包含三个关键点:

  • 基本可用(Basically Available):指系统在出现故障或部分节点不可用的情况下,仍能提供服务,但可能会在性能或功能上有所降级。例如双十一购物场景下,电商网站可能会牺牲部分页面的实时性,但保证下单支付核心功能可用。
  • 软状态(Soft State):指系统中的数据状态可以是中间状态,而不是强一致的瞬时状态。换句话说,数据在某一时刻可能不完全一致,但这种不一致是被系统允许和容忍的。
  • 最终一致性(Eventually Consistent):指经过一段时间的同步和修复,系统中的所有副本最终会达到一致状态。常见于异步复制或 Gossip 协议的场景,例如分布式缓存、消息队列。

BASE 理论的提出本质上是对 CAP 定理的一种工程解法:既然在分布式系统中强一致性和高可用无法兼得,那就优先保证高可用(A),同时通过软状态和最终一致性机制,在容忍一定“不一致”的前提下,换取系统整体的可扩展性和容错性。

分布式共识算法

在分布式系统中,单节点的故障是常态而不是例外。为了保证多个节点在面对网络分区、节点宕机、消息丢失等情况时仍能对外提供一致的服务,就需要依赖共识算法来达成多个节点之间的一致性。常见的共识算法有 Paxos、Raft 以及更轻量的 Gossip 协议。

一些常见的误解:使用了 Raft 或者 paxos 的系统都是线性一致性的(即强一致),其实不然,共识算法只能提供基础,要实现线性一致还需要在算法之上做出更多的努力。

Paxos 算法

Paxos 是由 Leslie Lamport 提出的经典分布式共识算法。它通过提议者(Proposer)、接受者(Acceptor)和学习者(Learner)三类角色,实现分布式节点之间对某个值的达成一致。Paxos 的理论完整性很高,但实现和理解相对复杂,因此在工业界大规模应用中较少直接使用,而更多是作为后续算法的理论基础。

Raft 算法

Raft 可以看作是对 Paxos 的工程化改进。它把复杂的一致性问题拆解为几个更容易理解的子问题:领导者选举日志复制安全性保证。在一个 Raft 集群中,始终会选出一个 Leader 节点,由 Leader 负责接收客户端请求并同步给 Follower 节点,保证日志顺序和状态机的一致性。由于设计简洁、逻辑清晰,Raft 已成为许多分布式系统(如 Etcd、Consul)的核心算法。这里是两篇帮助理解的可视化:Raft: Understandable Distributed ConsensusThe Raft Consensus Algorithm

Gossip 协议

Gossip 协议是一种允许在分布式系统中共享状态的去中心化通信协议,通过这种通信协议,我们可以将信息传播给网络或集群中的所有成员。它的思想源自现实生活中的“谣言传播”:每个节点定期随机选择其他节点,将自己已知的信息传递出去。随着时间推移,所有节点的信息会逐渐收敛到一致状态。Gossip 协议实现简单、扩展性强,特别适合节点规模庞大、对一致性要求不高的场景,例如健康检查、服务心跳同步和分布式缓存。

算法特点优点缺点 / 适用场景
Paxos最经典的分布式一致性算法,基于提议者、接受者、学习者三角色达成共识理论完整性高,保证强一致性,适合关键业务场景实现复杂,理解困难,工程实践中较少直接使用
Raft对 Paxos 的工程化改进,核心思路:领导者选举 + 日志复制 + 安全性保证易于理解和实现,逻辑清晰,广泛应用于 etcd、Consul 等系统仍需要领导者节点,Leader 崩溃会有短暂不可用,适合中小规模集群
Gossip去中心化协议,节点通过“谣言传播”逐步同步状态理解简单,易于实现。节点平等,扩散速度比单主节点快短时间内节点状态可能不一致(最终一致性),节点可能重复收到相同信息

服务发现方案

以下除 Nacos 内容,均转自分布式系统之服务发现(Service Discovery)。示意图来自 Service Discovery With CRDTs

DNS

DNS(Domain Name System)是一种通过解析域名获取 IP 和端口的机制。将 SRV 记录注册到 DNS 服务器上,通过 DNS 解析流程进行解析。但是 DNS 存在两个问题:一是当服务实例启动之后将 SRV 记录注册到 DNS 服务器上比较难,需要手动维护;二是 DNS 严重依赖缓存,服务使用方无法及时知道一个服务实例是否已经停止。

mDNS

mDNS(multicast DNS 即组播 DNS)是一种零配置的服务发现机制,在内部网络中经常使用,每个服务都有一个内置的 mDNS 响应程序,从而不需要单独的服务注册中心。mDNS 最大的问题就是要求网络基础设施支持 IP 多播(IP multicast),对于云环境来说显然是无法满足的,而且 mDNS 也无法解决 DNS 缓存问题。

DNS 与 mDNS 都具备良好的容错能力,但缺乏服务健康检查和变化通知机制。

Zookeeper

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

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

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

image.png

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 成为微服务架构中常用服务发现解决方案。

image.png

Consul

Consul 是一个成熟的服务发现解决方案。其核心是一个基于 Raft 共识算法具备线性强一致性的 Key-Value 存储系统作为服务注册中心,并提供代理(Agent)机制一方面用于协调服务注册,一方面提供服务健康检查。代理(Agent)会在每个运行服务的节点上启动,获取节点地址并将该服务实例注册到服务注册中心。架构上 Consul 包括两类组件:Server、Agent,服务注册信息保存在 Server 上,通过 Raft 共识算法保证多个 Server 间数据线性强一致,保证服务注册中心高可用;将所有 Agent 作为集群节点,使用 Gossip 协议进行组关系管理和故障探测,当有 Agent 加入(启动)或离开(故障)集群时其他 Agent 会得到通知,实现服务健康检查和监视功能。

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

image.png

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

Nacos

Nacos是阿里巴巴开源的一款易用平台,专为动态服务发现配置管理服务治理设计,旨在帮助开发者快速构建云原生应用和微服务平台。

  • 服务发现与健康检查

    • 服务实例可以通过 DNS 或 HTTP 接口注册自身,并发现其他服务。
    • 内置实时健康检查机制,可避免向不健康的服务实例发送请求,提高系统可靠性。
  • 动态配置管理

    • 提供集中式配置管理,可在运行时动态更新服务配置,而无需重新部署应用。
    • 支持跨环境配置管理和灰度发布,提高配置修改的效率与灵活性。
  • 动态 DNS 服务

    • 支持权重路由,可实现中间层负载均衡、灵活路由策略和流量控制。
    • 提供简单的 DNS 解析服务,方便在数据中心内部实现基于 DNS 的服务发现,降低应用对特定服务发现 API 的耦合。
  • 服务及元数据管理

    • 提供可视化服务管理控制台,可管理服务元数据、配置、Kubernetes DNS、服务健康状态和统计指标。
    • 帮助运维人员实时掌握服务状态和性能指标,便于治理和监控。
  • 集群与高可用

    • 支持集群部署,提高可用性和扩展性。
    • 多节点间可保证服务注册信息的一致性,并可容忍部分节点故障。
  • 安全与权限控制

    • 支持 SSL/TLS 加密及鉴权机制,但社区版本可能需要手动配置。

参考

本文作者:Zerol Acqua

本文链接:

版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!