服务注册与发现——Eureka

目录

注册中心

[CAP 理论](#CAP 理论)

常见注册中心

Zookeeper

Eureka

Nacos

[CAP 理论对比](#CAP 理论对比)

Eureka

组成部分

[Eureka Server(服务端)](#Eureka Server(服务端))

[Eureka Client(客户端)](#Eureka Client(客户端))

快速上手

[搭建 Eureka Server](#搭建 Eureka Server)

服务注册

服务发现


在上一篇文章 Spring Cloud 概述-CSDN博客 示例中,进行远程调用时,我们的 URL 是写死的:

String url = "http://127.0.0.1:9090/product/" + orderInfo.getProductId();

当我们需要更换或新增机器时,URL 也会随之发生变化,此时就需要修改对应的服务的 URL,并重新部署项目,非常繁琐

那么,我们如何解决这个问题呢?

注册中心

我们可以通过注册中心来帮我们完成 URL 管理:

服务方 启动或信息变更时,主动通知注册中心,注册中心记录相关信息

调用方 需要调用时,先去注册中心查询服务方对应信息,再进行调用

从上图可看出,注册中心主要涉及到三个角色

服务提供者(Service Provider): 启动时向注册中心注册自己的元数据 (服务名、IP、端口、健康状态、权重等),并定期发送心跳(或健康检查)维持注册状态 ,当下线时主动注销(或因超时被剔除)

服务消费者(Service Consumer): 从注册中心拉取或订阅目标服务的实例列表 ,并基于负载均衡策略(如轮询、随机、一致性哈希)选择实例发起调用,为避免每次调用都查询注册中心,可缓存服务列表并监听变更

注册中心(Registry):存储和管理服务实例的元数据 (服务名→实例列表的映射),维护服务健康状态 (通过心跳或主动探测)以及通知消费者服务变更(如实例上线/下线)

而它们之间的关系,可以通过以下两个概念来描述:

服务注册(Service Registration):服务提供者 实例启动时,将自己的网络地址(如IP、端口)、服务名称、健康状态等信息记录到注册中心

服务发现(Service Discovery):服务消费者 通过查询注册中心,获取可用服务实例列表,并基于负载均衡策略(如轮询、权重)选择实例发起调用

接下来,我们来学习一个重要的理论 ------ CAP 理论

CAP 理论

CAP 理论是分布式系统设计的核心原则,用于描述分布式系统中三个不可兼得的特性一致性(Consistency)可用性(Availability)分区容错性(Partition Tolerance)

C( Consistency,一致性): 所有节点在同一时间看到的数据完全一致**(强一致性)**

**A(Availability,可用性):**每个请求都能得到响应(不保证数据最新),系统始终可用。也就是说即使部分节点故障,服务仍可响应

**P(Partition Tolerance,分区容错性):**系统在网络分区(节点间通信中断)时仍能继续运行

但是,一个分布式系统不可能同时满足数据一致性服务可用性分区一致性 这三个基本需求,最多只能同时满足其中两个

那为什么最多只能同时满足其中两个呢?任意两个都可以满足吗?

在分布式系统中,系统之间的网络不可能 100% 保证健康 (即,可能会出现网络分区

而当网络分区发生 ,且保证分区容错(P满足) 的情况下,系统只能在C 和 A 中二选一

选择 C(一致性) :系统检测到节点间网络中断,为保证数据一致性,拒绝写入或读取 (如返回超时错误,此时系统对外不可用,不能满足 A),例如 Zookeeper 在 Leader 节点故障时,选举新 Leader 期间不可写入(满足 CP)

选择 A(可用性) : 系统继续响应请求,但不同分区可能返回不一致的数据 (如部分节点未同步最新写入,部分数据不同步,不能满足 C),例如 Eureka 在节点间网络中断时,各节点仍可提供服务,但服务列表可能不一致(满足 AP)

因此,CAP 理论中最多只能同时满足两个特性的核心原因在于:在网络分区(P)不可避免的分布式环境下,强一致性(C)和高可用性(A)在本质上存在冲突

而 CAP 的"三选二"本质是分布式系统在网络不可靠条件下的必然妥协:

选择 CP:适合对数据准确性要求高的场景(如银行转账)

选择 AP:适合对可用性要求高的场景(如电商商品展示)

CA 无意义:分布式系统必须面对网络分区(P)

接下来,我们来看常见的注册中心

常见注册中心

Zookeeper

Zookeeper 核心功能包括分布式协调服务,提供注册中心、分布式锁、配置管理等功能,基于 **ZAB(Zookeeper Atomic Broadcast)**协议,类似 Paxos

特点:

强一致性:所有节点数据实时同步,读写请求由 Leader 统一处理

高可靠性:适合金融、支付等对数据准确性要求高的场景

基于CP优先保证强一致性,牺牲部分可用性:

Leader 选举期间(约 200ms~几秒)服务不可用。

写入性能较低(需多数节点确认)

适用场景:

  1. Kafka、Hadoop、Dubbo 等分布式系统的元数据管

  2. 需要强一致性的服务注册与发现(如分布式锁)

Eureka

Eureka 主要用于服务注册与发现,Spring Cloud 默认集成

特点:

高可用性

  1. 节点间通过异步复制数据,容忍网络分区导致的数据不一致

  2. 客户端缓存服务列表,即使注册中心宕机仍可本地调用

简单轻量:无复杂依赖,适合中小规模集群

缺点:

数据最终一致性,可能读到旧数据

2.x 版本已停止维护

适用场景:

对一致性要求不高、需要快速响应的服务发现(如电商商品服务)

Nacos

Nacos 的核心功能包括 服务注册发现 + 动态配置管理 ,且支持 AP/CP 模式切换

特点:

灵活性

  1. AP 模式:基于自研 Distro 协议,高可用优先(类似 Eureka)

  2. CP 模式:基于 Raft 协议,强一致性优先(类似 Zookeeper)

高性能:支持百万级服务实例注册

生态集成:完美兼容 Spring Cloud、Kubernetes、Dubbo

适用场景:

  1. 云原生微服务(如 Kubernetes + Spring Cloud Alibaba)

  2. 需要同时满足服务发现和配置管理的场景

CAP 理论对比

注册中心 CAP 一致性协议 可用性表现 适用场景
Zookeeper CP ZAB 网络分区时拒绝写入 强一致性需求(如金融系统)
Eureka AP 无(异步复制) 网络分区仍响应,数据可能旧 高可用优先(如互联网应用)
Nacos AP/CP Distro/Raft 根据模式动态调整 灵活场景(云原生、混合部署)

接下来,我们就继续来学习 Eureka的使用

Eureka

Eureka 作为 Netflix 开源的 服务注册与发现组件 ,其架构主要由 两大部分 构成:Eureka Server (服务端)和 Eureka Client(客户端)

组成部分

Eureka Server(服务端)

**Eureka Server:**作为注册中心,存储和管理服务实例信息

核心功能:

服务注册中心:接收并管理所有微服务实例的注册信息(如服务名、IP、端口、健康状态)

服务列表维护 :通过心跳机制检测实例存活状态,自动剔除故障节点

服务信息同步 :在集群模式下,多个 Eureka Server 节点之间通过异步复制共享服务注册表

Eureka Client(客户端)

**Eureka Client:**负责处理服务注册、服务发现和心跳保活

核心功能:

服务注册:微服务启动时,向 Eureka Server 注册自身信息

服务发现:从 Eureka Server 拉取其他服务的实例列表,并缓存到本地

心跳保活:定期(默认30秒)向 Eureka Server 发送心跳,证明自身存活

负载均衡:结合 Ribbon 实现客户端负载均衡(如轮询、随机策略)

Eureka ClientEureka Server核心交互流程:

服务启动 :Client 向 Server 发送注册请求(POST /eureka/apps/{serviceId})。

心跳维持 :Client 定期发送心跳(PUT /eureka/apps/{serviceId}/{instanceId})。

服务发现 :Client 从 Server 拉取注册表(GET /eureka/apps),缓存到本地。

故障剔除 :Server 检测到心跳超时(默认90秒)后,将实例标记为下线(DELETE /eureka/apps/{serviceId}/{instanceId})。

接下来,我们就来学习如何快速使用 Eureka

快速上手

我们还是以之前的 订单服务和商品服务作为示例来进行学习,要想在其中使用 Eureka,需要完成以下三步:

  1. 搭建 Eureka Server

  2. 将 order-service 和 product-service 都注册到 Eureka Server

  3. order-service 在进行远程调用时,从 Eureka Server 获取 product-service 服务列表,再进行交互

搭建 Eureka Server

Eureka Server 是一个独立的微服务,因此我们需要先创建eureka-server子模块:

在 pom 文件中引入eureka-server 依赖和 项目构建插件:

XML 复制代码
    <dependencies>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

完善启动类,并在启动类 上添加 @EnableEurekaServer 注解,开启 Eureka 注册中心服务

java 复制代码
@EnableEurekaServer
@SpringBootApplication
public class EurekaServerApplication {
    public static void main(String[] args) {
        SpringApplication.run(EurekaServerApplication.class, args);
    }
}

完善配置文件:

java 复制代码
server:
  port: 10010
spring:
  application:
    name: eureka-server
eureka:
  instance:
    hostname: localhost
  client:
    fetch-registry: false # 表示是否从Eureka Server获取注册信息,默认为true.因为这是一个单点的Eureka Server,不需要同步其他的Eureka Server节点的数据,这里设置为false
    register-with-eureka: false # 表示是否将自己注册到Eureka Server,默认为true.由于当前应用就是Eureka Server,故而设置为false.
    service-url:
      # 设置Eureka Server的地址,查询服务和注册服务都需要依赖这个地址
      defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/
logging:
  pattern:
    console: '%d{MM-dd HH:mm:ss.SSS} %c %M %L [%thread] %m%n'

启动eureka-server ,访问 Eurekahttp://127.0.0.1:10010/

可以看到 Eureka 启动成功

接下来,我们将product-service 注册到eureka-server

服务注册

product-service 中引入eureka-client依赖:

XML 复制代码
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
        </dependency>

application.yml 中添加服务名称和 eureka 地址

java 复制代码
spring:
  application:
    name: product-service
eureka:
  client:
    service-url:
      defaultZone: http://127.0.0.1:10010/eureka/

启动 product-server,刷新注册中心:

可以看到 product-server 已经注册到 eureka 上了

服务发现

接下来我们继续修改 order-service,先将 order-service 注册到 eureka-server 中:

同样引入依赖:

product-service 中引入eureka-client依赖:

XML 复制代码
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
        </dependency>

application.yml 中添加服务名称和 eureka 地址

java 复制代码
spring:
  application:
    name: order-service
eureka:
  client:
    service-url:
      defaultZone: http://127.0.0.1:10010/eureka/

修改远程调用代码:

java 复制代码
@Slf4j
@Service
public class OrderService {
    @Autowired
    private OrderMapper orderMapper;
    @Autowired
    private RestTemplate restTemplate;
    @Autowired
    private DiscoveryClient discoveryClient;
    public OrderInfo findOrderInfoById(Integer orderId) {
        OrderInfo orderInfo = orderMapper.selectOrderById(orderId);
        // 根据应用名称获取服务列表
        List<ServiceInstance> instances = discoveryClient.getInstances("product-service");
        log.info("获取 product-service 实例列表:", instances.toString());
        EurekaServiceInstance instance = (EurekaServiceInstance)instances.get(0);
        log.info("选择实例: " + instance.getInstanceId());
        // 拼接 URL
        String url = instance.getUri() + "/product/" + orderInfo.getProductId();
        ProductInfo productInfo = restTemplate.getForObject(url, ProductInfo.class);
        orderInfo.setProductInfo(productInfo);
        return orderInfo;
    }
}

通过 DiscoveryClient 根据 服务名称获取服务列表,由于现在只有 1 个 product-server,因此我们直接获取列表中的第一个 product-server

启动order-server,刷新注册中心:

可以看到 order-service 也成功注册到 eureka 上

访问接口 127.0.0.1:8080/order/1

远程调用成功

在本篇文章中,我们对于服务注册和服务发现 ,以及Eureka有了基本的了解

在之后的文章中,我们再来进一步学习 Eureka 具体是如何实现服务注册和服务发现等核心功能的

相关推荐
码界奇点26 分钟前
基于Spring Cloud Alibaba与Vue.js的分布式在线教育系统设计与实现
前端·vue.js·分布式·spring cloud·架构·毕业设计·源代码管理
sg_knight1 小时前
Docker Engine 升级指南:保障容器安全的关键步骤
java·spring boot·安全·spring·spring cloud·docker·容器
码界奇点1 小时前
基于Spring Cloud Alibaba的分布式微服务权限管理系统设计与实现
分布式·spring cloud·微服务·架构·毕业设计·源代码管理
后端小张2 小时前
【JAVA进阶】鸿蒙开发与SpringBoot深度融合:从接口设计到服务部署全解析
java·spring boot·spring·spring cloud·华为·harmonyos·鸿蒙
carry杰2 小时前
Springboot3 + shardingsphere-jdbc5.5.2 按年月分表(动态创建表)
java·spring cloud
生骨大头菜13 小时前
使用python实现相似图片搜索功能,并接入springcloud
开发语言·python·spring cloud·微服务
YDS82916 小时前
SpringCould —— 网关详解
后端·spring·spring cloud
码界奇点19 小时前
基于微服务架构的悟空人力资源管理系统设计与实现
spring cloud·微服务·云原生·架构·毕业设计·源代码管理
周杰伦_Jay19 小时前
【BGE-M3与主流RAG嵌入模型】知识库嵌入模型对比
人工智能·机器学习·eureka·开源·github
大大大大物~21 小时前
Spring Cloud熔断与降级:核心区别与实践指南【怎么理解?解决了什么问题?各自的适用场景?Sentinel实现代码示例】
spring cloud·sentinel·熔断·降级