当前位置: 首页 > news >正文

Spring Cloud 微服务架构:Eureka 与 ZooKeeper 服务发现原理与实战指南 NO.1

一、微服务架构与服务发现

1.1 微服务架构概述

在当今数字化时代,随着业务的快速发展和用户需求的不断变化,软件系统面临着前所未有的挑战。传统的单体架构逐渐暴露出其局限性,如难以扩展、维护成本高、技术栈单一等问题。微服务架构应运而生,它将一个大型的单体应用拆分成多个小型、独立的服务,每个服务专注于特定的业务功能,这些服务可以独立开发、部署和扩展,从而实现了高内聚、低耦合的架构目标。

在微服务架构中,各个服务之间通过网络进行通信,这就带来了一个关键问题:如何让服务之间能够准确地找到彼此?这便是服务发现机制需要解决的核心问题。服务发现就像是一个智能的导航系统,帮助服务消费者在众多的服务提供者中找到合适的服务实例,实现高效的服务调用。

1.2 服务发现的重要性

在微服务架构中,服务实例的数量可能会随着业务的发展而动态变化,服务的上线、下线以及故障恢复等操作频繁发生。如果没有服务发现机制,服务消费者就需要手动配置和维护服务提供者的地址信息,这不仅工作量巨大,而且极易出错。一旦服务提供者的地址发生变化,服务消费者还需要及时更新配置,否则将导致服务调用失败。

服务发现机制能够自动感知服务实例的变化,当有新的服务实例上线时,它会自动将其注册到服务注册中心;当服务实例下线或出现故障时,也能及时从注册中心移除。这样,服务消费者只需从服务注册中心获取最新的服务实例列表,就能够始终与可用的服务提供者进行通信,大大提高了系统的稳定性和可靠性。

服务发现机制还能够与负载均衡、容错处理等功能相结合,实现对服务调用的优化。通过合理地选择服务实例,它可以有效地平衡系统负载,提高资源利用率;在面对服务实例故障时,能够快速进行故障转移,确保业务的连续性。

二、Eureka 服务发现原理

2.1 Eureka 架构概述

Eureka 是 Netflix 开源的一款服务发现工具,在 Spring Cloud 微服务架构中得到了广泛的应用。它采用了客户端 - 服务端架构模式,主要由 Eureka Server 和 Eureka Client 两部分组成。

Eureka Server 作为服务注册中心,负责接收、存储和管理服务实例的注册信息。它维护了一个服务注册表,记录了所有注册到该中心的服务实例的详细信息,包括服务名称、IP 地址、端口号、健康状态等。多个 Eureka Server 之间可以相互注册,形成一个高可用的集群,当某个 Eureka Server 节点出现故障时,其他节点能够继续提供服务注册与发现功能,确保系统的稳定性。

Eureka Client 则分为服务提供者和服务消费者两端。服务提供者在启动时,会通过 Eureka Client 向 Eureka Server 发送注册请求,将自身的服务信息注册到服务注册表中。同时,服务提供者会定期向 Eureka Server 发送心跳请求,以表明自己仍然存活,这个心跳机制是确保服务提供者状态实时更新的关键。如果 Eureka Server 在一定时间内(默认 90 秒)没有收到某个服务实例的心跳,则会将其从注册表中移除。

服务消费者在调用其他服务时,同样通过 Eureka Client 从 Eureka Server 获取目标服务的实例列表。Eureka Server 会返回所有可用的服务实例信息,服务消费者根据这些信息进行负载均衡和故障转移,选择合适的服务实例发起请求。

2.2 Eureka 服务注册流程

  1. 服务提供者启动:服务提供者应用启动时,首先会初始化 Eureka Client。在配置文件中,需要指定 Eureka Server 的地址等相关信息,以便 Eureka Client 能够找到服务注册中心。
  2. 注册服务:Eureka Client 将服务提供者的元数据信息(如服务名称、IP 地址、端口号、健康检查 URL 等)封装成一个注册请求,通过 HTTP 请求发送给 Eureka Server。这个注册请求中包含了服务提供者的关键信息,这些信息将被用于服务发现和调用。
  3. 服务维护:Eureka Server 接收到注册请求后,会将服务实例信息存储在本地的服务注册表中。同时,服务提供者会启动一个定时任务,周期性地向 Eureka Server 发送心跳包(本质是一个简单的 HTTP GET 请求)。Eureka Server 在收到心跳包后,会更新服务实例在注册表中的续约时间,以此来维持服务实例的存活状态。
  4. 服务实例状态更新:Eureka Server 会定期检查服务实例的心跳情况。如果在设定的过期时间内(默认 90 秒)没有收到某个服务实例的心跳,Eureka Server 会认为该实例已经离线,将其从服务注册表中删除。这样,服务消费者在获取服务实例列表时,就不会获取到已经离线的服务实例,从而保证了服务调用的有效性。

2.3 Eureka 服务发现流程

  1. 服务消费者请求:当服务消费者需要调用其他服务时,它会通过自身的 Eureka Client 向 Eureka Server 发送查询请求,请求中包含目标服务的名称。服务消费者通过这种方式,告知 Eureka Server 自己需要获取哪个服务的实例列表。
  2. 返回可用实例列表:Eureka Server 接收到服务消费者的请求后,会在其维护的服务注册表中查找目标服务的所有可用实例信息。这些实例信息包括每个服务实例的 IP 地址、端口号、健康状态等详细内容。然后,Eureka Server 将这些可用实例列表返回给服务消费者的 Eureka Client。
  3. 负载均衡与服务调用:服务消费者的 Eureka Client 接收到可用实例列表后,会结合负载均衡策略选择一个合适的服务实例进行通信。常见的负载均衡策略有轮询、随机、加权轮询等。例如,采用轮询策略时,Eureka Client 会按照顺序依次选择服务实例;采用加权轮询策略时,会根据服务实例的性能指标(如响应时间、吞吐量等)为每个实例分配不同的权重,然后按照权重比例选择实例。选定服务实例后,服务消费者就可以向该实例发起实际的服务调用请求,获取所需的服务。

2.4 Eureka 自我保护机制

在分布式系统中,网络分区等异常情况时有发生。当出现网络分区时,部分 Eureka Server 节点可能无法与服务提供者进行正常通信,导致这些节点收不到服务提供者的心跳。如果按照正常的机制,Eureka Server 会将这些服务实例从注册表中移除。但实际上,这些服务实例可能仍然在正常运行,只是由于网络问题导致无法与 Eureka Server 通信。

为了应对这种情况,Eureka 引入了自我保护机制。当 Eureka Server 在 15 分钟内,检测到超过 85% 的客户端都没有进行服务续约时,它会认为系统可能出现了网络分区等异常情况,进而进入自我保护模式。

在自我保护模式下,Eureka Server 不再剔除没有续约的服务实例,而是继续保留它们在注册表中的信息。同时,Eureka Server 只接收新客户端的注册和服务查询请求,对于其他可能导致服务实例状态变更的操作(如服务实例的下线、过期剔除等),则暂时停止执行。这样可以避免在网络异常期间,误将正常运行的服务实例从注册表中移除,保证了系统的可用性。

当网络恢复正常后,Eureka Server 会自动退出自我保护模式,恢复正常的服务实例管理机制。自我保护机制是 Eureka 在复杂的分布式环境中保证系统稳定性的一项重要措施,它在一定程度上牺牲了数据的一致性,以换取更高的可用性。

三、ZooKeeper 服务发现原理

3.1 ZooKeeper 架构概述

ZooKeeper 是一个开源的分布式协调服务,它为分布式应用程序提供了一种可靠的、高性能的、分布式协同的数据管理服务。在微服务架构中,ZooKeeper 常被用于实现服务发现功能。

ZooKeeper 采用了主从架构,集群由一个 Leader 节点和多个 Follower 节点组成。Leader 节点负责处理客户端的写请求,并将数据变更同步到 Follower 节点。Follower 节点主要负责处理客户端的读请求,同时接收 Leader 节点的数据同步请求,保持与 Leader 节点的数据一致性。

ZooKeeper 的数据模型类似于文件系统,采用树形结构。每个节点被称为 ZNode,ZNode 可以存储数据和子节点。在服务发现场景中,ZooKeeper 利用临时节点和 Watcher 机制来实现服务的注册与发现。

3.2 ZooKeeper 服务注册流程

  1. 服务提供者启动:服务提供者应用启动后,会创建一个 ZooKeeper 客户端连接,连接到 ZooKeeper 集群。在连接过程中,需要指定 ZooKeeper 集群的地址等相关配置信息。
  2. 创建临时节点:服务提供者通过 ZooKeeper 客户端在指定的服务节点路径下创建一个临时节点。例如,假设服务名称为 “user - service”,服务提供者会在 “/services/user - service” 路径下创建一个临时节点。这个临时节点的名称通常包含服务提供者的 IP 地址、端口号等唯一标识信息。由于是临时节点,当服务提供者与 ZooKeeper 集群的连接断开时,该节点会自动被 ZooKeeper 删除,从而实现了服务实例的自动下线功能。
  3. 存储服务信息:在创建临时节点的同时,服务提供者会将自身的服务元数据信息(如服务名称、IP 地址、端口号、服务版本、健康检查 URL 等)存储到该临时节点的数据部分。这些信息将被服务消费者用于发现和调用服务。

3.3 ZooKeeper 服务发现流程

  1. 服务消费者启动:服务消费者应用启动后,同样会创建一个 ZooKeeper 客户端连接到 ZooKeeper 集群。
  2. 获取服务实例列表:服务消费者通过 ZooKeeper 客户端监听指定服务节点路径(如 “/services/user - service”)下的子节点变化。当服务消费者首次连接到 ZooKeeper 集群时,它会立即获取该路径下的所有子节点信息。这些子节点代表了当前可用的服务提供者实例。
  3. 服务调用:服务消费者从获取到的子节点信息中解析出每个服务提供者的元数据信息,然后根据一定的负载均衡策略选择一个服务实例进行调用。与 Eureka 类似,常见的负载均衡策略有轮询、随机、加权轮询等。在选择服务实例时,服务消费者会优先选择健康状态良好的实例进行调用。

3.4 ZooKeeper 的 Watcher 机制

Watcher 机制是 ZooKeeper 实现分布式通知的核心机制,在服务发现过程中起着至关重要的作用。当服务消费者通过 ZooKeeper 客户端监听某个服务节点路径下的子节点变化时,实际上是在 ZooKeeper 服务器上注册了一个 Watcher。

当 ZooKeeper 服务器上该路径下的子节点发生变化(如新增子节点、删除子节点、子节点数据变更等)时,ZooKeeper 服务器会向注册了 Watcher 的服务消费者发送通知。服务消费者在接收到通知后,会再次获取该路径下的最新子节点信息,从而及时更新本地维护的服务实例列表。

例如,当有新的服务提供者上线时,它会在 ZooKeeper 上创建对应的临时节点,此时服务消费者注册的 Watcher 会被触发,服务消费者就能及时得知有新的服务实例可用;当某个服务提供者下线时,其对应的临时节点会被 ZooKeeper 自动删除,同样会触发服务消费者的 Watcher,服务消费者可以及时将该下线的服务实例从本地列表中移除。通过这种方式,Watcher 机制确保了服务消费者能够实时感知服务实例的变化,保证了服务发现的实时性和准确性。

四、Eureka 与 ZooKeeper 对比分析

4.1 一致性模型

Eureka 采用的是 AP(可用性 - 分区容错性)一致性模型。在 Eureka 的设计中,更侧重于保证系统的可用性。它允许在一定时间内,不同的 Eureka Server 节点之间的数据存在不一致的情况。例如,在网络分区期间,部分 Eureka Server 节点可能无法及时同步服务实例的最新状态,但这些节点仍然能够对外提供服务注册和发现功能,以确保服务消费者能够获取到服务实例列表,尽管这个列表可能不是最新的。这种设计使得 Eureka 在面对网络故障等异常情况时,能够保证系统的基本运行,不会因为数据一致性问题而导致服务不可用。

ZooKeeper 采用的是 CP(一致性 - 分区容错性)一致性模型。ZooKeeper 通过 Zab 协议实现了强一致性,确保在任何时刻,集群中所有节点的数据都是一致的。在 ZooKeeper 集群中,所有的写操作都必须经过 Leader 节点,Leader 节点会将数据变更同步到所有的 Follower 节点,只有当大多数节点(超过半数)都成功同步数据后,写操作才会被认为是成功的。这种强一致性保证了在服务发现过程中,服务消费者获取到的服务实例列表始终是最新的、一致的。但在网络分区等情况下,为了保证数据一致性,ZooKeeper 可能会暂停部分服务,牺牲一定的可用性。

4.2 可用性与容错性

Eureka 通过多节点集群部署来实现高可用性。多个 Eureka Server 节点之间相互注册,形成一个集群。当某个 Eureka Server 节点出现故障时,其他节点能够继续提供服务注册和发现功能。而且,Eureka 的自我保护机制在一定程度上增强了系统的容错性,即使在网络分区等异常情况下,也能避免误删服务实例,保证系统的基本可用性。

ZooKeeper 同样通过集群部署来提高可用性。在 ZooKeeper 集群中,只要有超过半数的节点正常运行,集群就能够正常工作。当 Leader 节点出现故障时,集群会通过选举机制重新选出一个新的 Leader 节点,确保系统的正常运行。然而,由于 ZooKeeper 采用的是 CP 一致性模型,在网络分区等情况下,为了保证数据一致性,可能会导致部分服务不可用,其容错性在某些场景下相对较弱。

4.3 性能与扩展性

Eureka 在性能方面表现较好,它的服务注册和发现过程相对简单,采用 RESTful 接口进行通信,开销较小。在扩展性方面,Eureka Server 节点之间相互独立,新增节点较为容易,能够较好地适应大规模微服务架构的需求。当服务实例数量增加时,Eureka Server 的性能下降相对平缓。

ZooKeeper 在处理读请求时性能较高,因为 Follower 节点可以分担读请求的压力。但在处理写请求时,由于所有写操作都要经过 Leader 节点,并且需要同步到大多数节点,性能会受到一定影响。在扩展性方面,随着 ZooKeeper 集群规模的不断扩大,节点之间的通信和数据同步开销会逐渐增大,对系统性能产生一定的挑战。因此,在大规模微服务架构中,ZooKeeper 的扩展性相对 Eureka 略逊一筹。

4.4 适用场景

Eureka 适用于对系统可用性要求较高,允许在一定时间内存在数据不一致情况的场景。例如,在一些互联网电商系统中,服务的快速发现和调用是关键,即使偶尔获取到的服务实例列表不是最新的,也不会对业务产生严重影响。而且在云环境中,网络故障较为常见,Eureka 的自我保护机制和 AP 一致性模型能够更好地适应这种环境。

ZooKeeper 适用于对数据一致性要求极高的场景,如分布式事务协调、配置管理等场景。在这些场景中,数据的一致性至关重要,即使牺牲一定的可用性也在所不惜。例如,在金融领域的一些关键业务系统中,确保服务实例信息的一致性是保证业务正确运行的基础,ZooKeeper 的 CP 一致性模型能够满足这种严格的需求。

五、Spring Cloud 集成 Eureka 实战

5.1 搭建 Eureka Server

  1. 创建 Spring Boot 项目:首先,通过 Spring Initializr 创建一个新的 Spring Boot 项目。在创建过程中,选择合适的 Spring Boot 版本,并添加 “Eureka Server” 依赖。例如,在 Maven 项目中,添加如下依赖:

xml

<dependency><groupId>org.springframework.cloud</groupId><artifactId>spring - cloud - starter - netflix - eureka - server</artifactId>
</dependency>

  1. 配置 Eureka Server:在项目的配置文件(application.properties 或 application.yml)中,配置 Eureka Server 的相关属性。例如,设置 Eureka Server 的端口号、服务注册中心的地址等。以下是一个 application.yml 的配置示例:

yaml

server:port: 8761
eureka:instance:hostname: localhostclient:register - with - eureka: falsefetch - registry: false

上述配置中,将 Eureka Server 的端口设置为 8761,并且通过 “register - with - eureka: false” 和 “fetch - registry: false” 配置项,使当前 Eureka Server 节点不向其他 Eureka Server 节点注册自己,也不从其他节点获取服务注册信息,因为它本身就是服务注册中心的核心节点。
3. 启用 Eureka Server:在 Spring Boot 应用的主类上添加 “@EnableEurekaServer” 注解,启用 Eureka Server 功能。例如:

java

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer;@SpringBootApplication
@EnableEurekaServer
public class EurekaServerApplication {public static void main(String[] args) {SpringApplication.run(EurekaServerApplication.class, args);}
}

完成上述步骤后,启动 Spring Boot 应用,Eureka Server 就搭建成功了。可以通过浏览器访问 “http://localhost:8761/”,查看 Eureka Server 的管理界面,此时界面上应该还没有任何服务实例注册信息。

5.2 服务提供者注册到 Eureka

  1. 创建服务提供者项目:同样通过 Spring Initializr 创建一个新的 Spring Boot 项目,作为服务提供者。在创建时,添加 “Eureka Client” 依赖以及其他与业务相关的依赖。例如,添加如下 Maven 依赖:

xml

<dependency><groupId>org.springframework.cloud</groupId>

http://www.lryc.cn/news/625989.html

相关文章:

  • Stream API-怎么理解流
  • Day13_【DataFrame数据组合merge连接】【案例】
  • Redis(11)如何通过命令行操作Redis?
  • 反向代理实现服务器联网
  • 人工神经网络MATLAB工具箱指南
  • Selenium自动化测试入门:cookie处理
  • electron进程间通信- 渲染进程与主进程双向通信
  • 如何用给各种IDE配置R语言环境
  • UGUI源码剖析(10):总结——基于源码分析的UGUI设计原则与性能优化策略
  • Ubuntu 和麒麟系统创建新用户 webapp、配置密码、赋予 sudo 权限并禁用 root 的 SSH 登录的详细
  • Python os 模块与路径操作:从基础到实战应用
  • 《AI 与人类创造力:是替代者还是 “超级协作者”?》​
  • 读《精益数据分析》:营收(Revenue)—— 设计可持续盈利模式
  • RabbitMQ:SpringAMQP 入门案例
  • Day22 顺序表与链表的实现及应用(含字典功能与操作对比)
  • 计算机大数据毕业设计推荐:基于Spark的气候疾病传播可视化分析系统【Hadoop、python、spark】
  • QT示例 基于Subdiv2D的Voronoi图实现鼠标点击屏幕碎裂掉落特效
  • jmetergrafanainfluxdb搭建压测监控平台
  • C# NX二次开发:操作按钮控件Button和标签控件Label详解
  • CentOS上安装Docker的完整流程
  • 可以一键生成PPT的AI PPT工具(最新整理)
  • AiPPT怎么样?好用吗?
  • Lecture 12: Concurrency 5
  • 大数据毕业设计选题推荐:护肤品店铺运营数据可视化分析系统详解
  • 106、【OS】【Nuttx】【周边】文档构建渲染:安装 Sphinx 扩展(下)
  • OptiTrack光学跟踪系统,提高机器人活动精度
  • 电影购票+票房预测系统 - 后端项目介绍(附源码)
  • Qt密码生成器项目开发教程 - 安全可靠的随机密码生成工具
  • SpringBoot-集成POI和EasyExecl
  • SpringAIAlibaba之基础功能和基础类源码解析(2)