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

微服务的“导航系统”:使用Spring Cloud Eureka实现服务注册与发现

在上一篇中,我们理解了微服务架构的核心理念以及Spring Cloud为我们提供的强大工具集。我们提到,微服务架构的一个核心挑战在于,服务实例的网络位置是动态的,服务之间需要一种机制来互相定位。

想象一下,你开了一家新店(一个微服务实例),你希望顾客(其他服务或客户端)能找到你。你会怎么做?

  1. 注册: 你会去工商局(服务注册中心)登记你的店名、地址、联系方式等信息。

  2. 发现: 顾客想找你这家店时,会去工商局查询你的信息,然后根据地址找过来。

  3. 健康检查/心跳: 你需要定期向工商局报告你还在正常营业(发送心跳),如果长时间不报告,工商局可能会认为你的店关门了,就不会再把你的信息给顾客。

Spring Cloud Netflix Eureka (简称 Eureka) 就是这样一个“工商局”。它包含两个核心组件:

  • Eureka Server (服务注册中心): 提供服务注册和发现的功能。所有服务提供者(Eureka Client)启动时向Eureka Server注册自己的信息(服务名、IP、端口、健康状况等),并定期发送心跳来维持注册状态。Eureka Server会维护一个所有已注册服务实例的清单。

  • Eureka Client (服务提供者/消费者):

    • 作为服务提供者,它会向Eureka Server注册自己。

    • 作为服务消费者,它会从Eureka Server拉取注册表信息,缓存到本地,并根据服务名(通常结合客户端负载均衡器如Spring Cloud LoadBalancer)找到目标服务的实例地址进行调用。

Eureka的核心优势在于其AP(可用性优先)设计哲学 (基于CAP理论)。 即使部分Eureka Server节点失效,只要客户端缓存了注册表信息,仍然可以进行服务调用。Eureka Server之间也会互相复制注册信息,实现高可用。

读完本文,你将能够:

  • 搭建一个独立的Eureka Server。

  • 将一个Spring Boot应用配置为Eureka Client,并将其注册到Eureka Server。

  • 理解服务注册、服务发现和心跳机制的基本工作流程。

  • 通过Eureka Server的Web界面查看已注册的服务。

准备好为你的微服务们建立一个可靠的“导航系统”了吗?

一、搭建Eureka Server (服务注册中心)

Eureka Server本身也是一个Spring Boot应用。

1. 创建Spring Boot项目 (Eureka Server):
使用Spring Initializr (start.spring.io) 或你的IDE创建一个新的Spring Boot项目,包含以下依赖:

  • Spring Web: Eureka Server提供Web界面和REST API。

  • Eureka Server: 核心依赖,用于构建Eureka注册中心。

Maven依赖 (pom.xml):

<dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-netflix-eureka-server</artifactId></dependency><!-- Spring Cloud BOM (Bill of Materials) for version management -->
</dependencies><dependencyManagement><dependencies><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-dependencies</artifactId><version>${spring-cloud.version}</version> <!-- 例如: 2022.0.4 --><type>pom</type><scope>import</scope></dependency></dependencies>
</dependencyManagement>

注意: 务必在<dependencyManagement>中引入spring-cloud-dependencies BOM来统一管理Spring Cloud各个组件的版本。spring-cloud.version需要与你的Spring Boot版本兼容(参考Spring Cloud官网的版本对应关系)。

2. 启用Eureka Server (@EnableEurekaServer):
在主启动类上添加@EnableEurekaServer注解。

package com.example.eurekaserver;import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer; // 导入@SpringBootApplication
@EnableEurekaServer // 标记这个应用是一个Eureka Server
public class EurekaServerApplication {public static void main(String[] args) {SpringApplication.run(EurekaServerApplication.class, args);}
}

3. 配置Eureka Server (application.yml 或 application.properties):

# application.yml for Eureka Server
server:port: 8761 # Eureka Server的默认端口spring:application:name: eureka-server # 应用名称, 会显示在Eureka管理界面eureka:instance:hostname: localhost # Eureka实例的主机名 (单机配置)# (可选) instance-id: ${spring.application.name}:${server.port}client:# 对于单机Eureka Server, 这两项通常设为false, 因为它自己就是注册中心, 不需要注册自己或从其他地方获取注册信息register-with-eureka: false # 是否将自己注册到Eureka Server (自己就是server, 所以是false)fetch-registry: false       # 是否从Eureka Server获取注册信息 (自己就是server, 所以是false)service-url:# 对于单机模式, 这个地址指向自己 (通常不需要, 因为上面两项为false)# 但如果要搭建集群, 这里会配置其他Eureka Server节点的地址defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/# (可选) 关闭自我保护模式 (开发时方便快速看到服务下线, 生产环境不建议关闭)# server:#   enable-self-preservation: false#   eviction-interval-timer-in-ms: 5000 # 清理无效节点的时间间隔 (毫秒)

核心配置解释:

  • server.port: Eureka Server运行的端口,约定俗成为8761。

  • spring.application.name: 应用名,会显示在Eureka的管理界面。

  • eureka.client.register-with-eureka: false: 因为这个应用本身就是Eureka Server,所以它不需要向自己注册。

  • eureka.client.fetch-registry: false: 同理,它不需要从自己这里获取注册表。

  • eureka.client.service-url.defaultZone: 指定Eureka Server的地址。对于单机模式,这个配置虽然写了,但因为上面两项为false,实际作用不大。在Eureka Client端配置这个地址才至关重要。 当搭建Eureka Server集群时,这里会配置其他Peer节点的地址,用于节点间同步注册信息。

  • eureka.server.enable-self-preservation: Eureka的自我保护模式。在网络分区等情况下,如果Eureka Server在短时间内丢失了大量服务实例的心跳,它会进入自我保护模式,不再剔除这些“暂时失联”的实例,以防止因网络问题导致大量可用服务被错误移除。开发时为了快速看到服务下线效果,有时会临时关闭它,但生产环境通常应保持开启

4. 运行Eureka Server:
启动这个Spring Boot应用。如果一切顺利,你可以在浏览器中访问 http://localhost:8761/,看到Eureka的Web管理界面。此时,界面上应该还没有任何服务实例注册。

二、创建服务提供者 (Eureka Client)

现在我们来创建一个简单的Spring Boot应用,并让它作为服务提供者注册到刚才搭建的Eureka Server上。

1. 创建Spring Boot项目 (例如 user-service):
包含以下依赖:

  • Spring Web: 提供REST API。

  • Eureka Discovery Client: 核心依赖,用于将应用注册为Eureka客户端。

  • (可选) Spring Boot Actuator: 用于健康检查。

Maven依赖 (pom.xml - user-service):

<dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-netflix-eureka-client</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-actuator</artifactId> <!-- 用于健康检查 --></dependency><!-- Spring Cloud BOM (确保与Eureka Server项目使用相同的BOM版本) -->
</dependencies><dependencyManagement><dependencies><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-dependencies</artifactId><version>${spring-cloud.version}</version><type>pom</type><scope>import</scope></dependency></dependencies>
</dependencyManagement>

2. 启用Eureka Client (@EnableDiscoveryClient 或 @EnableEurekaClient):
在主启动类上添加注解。@EnableDiscoveryClient是Spring Cloud提供的更通用的服务发现注解(可用于Eureka, Consul, Nacos等),而@EnableEurekaClient是专门针对Eureka的。推荐使用@EnableDiscoveryClient。

package com.example.userservice;import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient; // 推荐使用@SpringBootApplication
@EnableDiscoveryClient // 标记这个应用是一个服务发现客户端 (可以注册和发现服务)
// 或者 @EnableEurekaClient // 仅适用于Eureka
public class UserServiceApplication {public static void main(String[] args) {SpringApplication.run(UserServiceApplication.class, args);}
}

3. 配置Eureka Client (application.yml - user-service):

# application.yml for user-service
server:port: 8081 # 服务提供者运行的端口 (确保与Eureka Server端口不同)spring:application:name: user-service # 服务名称, 这是注册到Eureka Server上的关键标识!# 服务消费者会通过这个名称来查找服务实例eureka:client:# register-with-eureka: true # (默认即为true) 是否将自己注册到Eureka Server# fetch-registry: true       # (默认即为true) 是否从Eureka Server获取注册信息service-url:defaultZone: http://localhost:8761/eureka/ # 指定Eureka Server的地址!instance:# (可选) 自定义实例ID, 默认为 ${spring.application.name}:${server.port}# instance-id: ${spring.application.name}:${random.value} # 可以使用随机值避免端口冲突时的ID冲突hostname: localhost # (可选) 如果需要让Eureka Server显示特定的主机名# (可选) 配置健康检查URL, Actuator的/actuator/health端点会自动被Eureka使用# health-check-url-path: /actuator/health# status-page-url-path: /actuator/info# (可选) 配置心跳间隔 (默认30秒)# lease-renewal-interval-in-seconds: 10# (可选) 配置服务过期时间 (默认90秒, 即如果90秒内没收到心跳, 实例被剔除)# lease-expiration-duration-in-seconds: 30

核心配置解释:

  • server.port: 这个服务提供者运行的端口,确保与Eureka Server的端口不同。

  • spring.application.name: 极其重要! 这是服务注册到Eureka Server时使用的服务名 (Service ID)。其他服务将来会通过这个服务名来发现和调用它。

  • eureka.client.service-url.defaultZone: 必须正确配置! 指向你的Eureka Server的地址。

  • eureka.instance.*: 可以配置实例相关的元数据,如实例ID、主机名、健康检查路径等。如果引入了spring-boot-starter-actuator,Eureka Client会自动使用/actuator/health端点作为健康检查URL。

4. (可选)创建一个简单的REST Controller (user-service):

package com.example.userservice.controller;import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;@RestController
@RequestMapping("/users")
public class UserController {@Value("${server.port}") // 注入当前服务端口, 方便演示private String serverPort;@GetMapping("/{id}")public String getUserById(@PathVariable Long id) {return "User details for ID " + id + " (from port: " + serverPort + ")";}
}

5. 运行服务提供者 (user-service):
启动这个user-service应用。稍等片刻(默认心跳间隔30秒,注册可能需要一点时间),然后刷新Eureka Server的管理界面 (http://localhost:8761/)。

你应该能在 "Instances currently registered with Eureka" 部分看到名为 USER-SERVICE (通常是大写) 的服务,以及它的实例信息(IP、端口、状态等)。状态初始可能是STARTING,之后会变为UP(如果健康检查通过)。

三、理解核心机制

  • 服务注册 (Registration): Eureka Client(如user-service)启动后,会向eureka.client.service-url.defaultZone配置的Eureka Server地址发送注册请求,包含自己的服务名、IP、端口、健康状况等信息。

  • 服务续约/心跳 (Renewal/Heartbeat): Client会定期(默认30秒)向Server发送心跳,告知Server自己仍然存活。如果Server在一定时间内(默认90秒)没有收到某个实例的心跳,会认为该实例已下线,并将其从注册表中剔除(除非开启了自我保护模式且触发了保护条件)。

  • 服务发现 (Discovery): 其他Client(服务消费者)启动时或定期(默认30秒)从Eureka Server拉取最新的服务注册表信息,并缓存到本地。当需要调用某个服务时,它会从本地缓存的注册表中根据服务名查找可用的实例列表。

  • 服务下线 (Cancellation): Client在正常关闭时,会向Server发送一个取消注册的请求。

四、高可用Eureka Server集群 (简述)

在生产环境中,单个Eureka Server节点是单点故障。通常会搭建Eureka Server集群来实现高可用。

配置集群的关键在于让每个Eureka Server节点知道其他节点的存在,并通过eureka.client.service-url.defaultZone互相指定对方的地址(但仍然将register-with-eureka和fetch-registry设为true,因为它们既是Server也是Client,需要同步注册信息)。

例如,两个节点的集群配置 (application-peer1.yml):

server:port: 8761
spring:application:name: eureka-server
eureka:instance:hostname: peer1 # 或真实IP/域名client:register-with-eureka: true # 注册到其他peerfetch-registry: true       # 从其他peer获取信息service-url:defaultZone: http://peer2:8762/eureka/ # 指向另一个节点

application-peer2.yml 对应配置 peer1:8761。
客户端的defaultZone则配置所有Eureka Server节点的地址,用逗号分隔。

五、总结:迈出微服务的第一步

通过搭建Eureka Server和配置Eureka Client,我们成功地让一个微服务实例(user-service)注册到了服务注册中心,并且可以通过Eureka的Web界面查看到它的状态。这为后续的服务间调用打下了坚实的基础。

Spring Cloud Netflix Eureka提供了一种相对简单且经过广泛验证的服务注册与发现解决方案。虽然Netflix已将其置于维护模式,但它在许多现有系统中仍被大量使用,并且其AP设计理念对于理解服务发现非常重要。

在后续的文章中,我们将看到服务消费者如何利用从Eureka获取到的信息,结合客户端负载均衡器来调用这个user-service。我们也会在适当的时候介绍更新的服务发现组件,如Nacos或Consul。

相关文章:

  • Qt6.5.3 windows下安装教程
  • 微信小程序的开发及问题解决
  • 力扣-226.翻转二叉树
  • Linux基础 -- 用户态Generic Netlink库高性能接收与回调框架
  • 免费实用的远程办公方案​
  • 基于RT-Thread的STM32F4开发第三讲——DAC
  • flinksql实践(从kafka读数据)
  • GZip+Base64压缩字符串在ios上解压报错问题解决(安卓、PC模拟器正常)
  • 基于FPGA的视频接口之千兆网口(七GigE)
  • C++—特殊类设计设计模式
  • 【Linux学习笔记】理解一切皆文件实现原理和文件缓冲区
  • 文件同步2
  • 用 VS Code / PyCharm 编写你的第一个 Python 程序
  • aardio - 虚表 —— vlistEx.listbar2 多层菜单演示
  • 【笔记】C++操作mysql及相关配置
  • 【MapReduce入门】深度解析MapReduce:定义、核心特点、优缺点及适用场景
  • conda 输出指定python环境的库 输出为 yaml文件
  • android抓包踩坑记录
  • SpringSecurity当中的CSRF防范详解
  • 香橙派zero3 安卓TV12,更换桌面launcher,开机自启动kodi
  • 学习教育期间违规吃喝,李献林、叶金广等人被通报
  • 著名连环画家庞邦本逝世
  • 工人日报:“鼠标手”被纳入职业病,劳动保障网越织越密
  • 上海现有超12.3万名注册护士,本科及以上学历占一半
  • 刘国中:持续加强护士队伍建设,更好保障人民身体健康
  • 韩国大选连发“五月惊奇”:在野党刚“摆脱”官司,执政党又生“内讧”