Spring Cloud 微服务实战(二):Eureka注册中心------单机与高可用集群搭建
个人主页:夏天拐跑了西瓜
专栏传送门:《大模型应用开发》、《Spring 生态全家桶体系化实战》
学习方向:Java 后端|AI‑Agent 大模型应用开发爱好者
⭐人生格言:路虽远,行则将至

上一篇聊完微服务概念,这篇我们正式动手。很多同学学SpringCloud第一天就搭Eureka,但搭完只知道"加依赖、加注解、改配置"三板斧,出了问题完全不知道从哪查。这篇我不仅带你搭起来,还会把我踩过的坑都写出来。
🎉 阅读本文你将收获:
- ✅ 从"硬编码IP调用"的痛点理解注册中心本质
- ✅ Eureka Server与Client分别在干什么
- ✅ 单节点Eureka从0到1搭建(可直接复制运行)
- ✅ 服务注册与调用完整链路跑通
- ✅ Eureka高可用集群为什么要互相注册
- ✅ Actuator监控端点怎么用
- ✅ 我当年踩过的5个坑及解决方案
- ✅ 3道面试高频题
👨💻 运行环境:JDK 8 + SpringBoot 2.2.5.RELEASE + SpringCloud Hoxton.SR3
一、先说个我刚工作时的糗事
我第一次做微服务项目的时候,前辈让我把订单服务和用户服务拆出来,我当时不知道有注册中心这种东西,直接在订单服务里写死了用户服务的IP:
java
private static final String USER_SERVICE = "http://192.168.1.100:8080";
结果测试环境重启后IP变了,订单调不通,我还去问运维是不是机器坏了。后来才知道有个东西叫"服务注册中心",专门解决这个问题。
如果你也写过这种硬编码IP,或者在properties里维护一堆服务地址,那你一定能理解注册中心的价值。
微服务拆分后,每个服务可能部署多个实例,IP随时可能变(扩容、缩容、故障转移、K8s调度),如果靠人工维护地址清单,维护成本极高且容易出错。注册中心就像是微服务世界的"114查号台":
- 服务启动时主动到注册中心"登记"自己的地址
- 调用方不用记IP,只说服务名,注册中心告诉你"这个服务现在有哪几个实例可用"
- 服务挂了注册中心会自动把它从清单里摘掉
这就是服务注册与发现的核心思想。
目前市面上主流的注册中心有Eureka、Nacos、Consul、Zookeeper等。我们这系列先从Eureka讲起,虽然现在新项目大多用Nacos,但Eureka的原理最经典,理解了它再学Nacos会非常快。
二、Eureka的两个角色
Eureka是Netflix公司开源的(就是那个做美剧和电影的Netflix,技术也很厉害),基于REST协议实现服务发现。SpringCloud把它整合进来,成为了SpringCloud Netflix体系的注册中心。
Eureka采用的是C/S架构,分两个角色:
- Eureka Server:注册中心服务端,是一个独立部署的Web应用,负责维护所有服务的注册表
- Eureka Client:各个微服务,启动时把自己注册到Server,同时定期从Server拉取最新的服务列表缓存到本地
需要特别注意一点:Eureka Server自己也是一个Eureka Client。它默认会把自己也注册上去,所以单节点模式下我们要手动把注册关掉,不然它会疯狂报错说找不到注册中心。
我画了一张图来表示它们之间的交互:
┌──────────────────────┐
│ Eureka Server │
│ (注册表在内存中) │
│ │
│ peer1 ←──→ peer2 │ ← 集群节点互相同步
└──────────▲───────────┘
│
┌────────────────────┼────────────────────┐
│ 注册/续约/下线 │ 拉取注册表 │ 注册/续约/下线
│ │ │
┌─────┴─────┐ ┌────┴──────┐ ┌────┴─────┐
│ Provider │ │ Consumer │ │ 其他服务 │
│ (客户端) │◄───────│ (客户端) │ │ (客户端) │
└───────────┘ 调用 └───────────┘ └──────────┘
几个核心交互:
- Register(注册):Client启动时告诉Server"我是谁,我在哪"
- Renew(续约/心跳):Client每隔30秒给Server发一次心跳,证明自己还活着
- Cancel(下线):服务正常关闭时主动告诉Server把自己摘掉
- Evict(剔除):Server默认90秒没收到心跳,就认为这个实例挂了,从注册表删掉
- Fetch Registry(拉取注册表):Client每隔30秒从Server拉一次最新服务列表,缓存到本地
- Remote Call(远程调用):Consumer从本地缓存里找到Provider地址,通过HTTP调用
后面讲Eureka原理的文章会详细分析这些机制,这一篇我们先把环境搭起来。
三、工程搭建
我习惯用Maven多模块来组织示例代码,这样每个组件对应一个子工程,版本统一在父pom管理,不用每个模块都写版本号。
最终工程结构如下:
eureka-demo/
├── pom.xml # 父POM,统一版本
├── eureka-server/ # Eureka注册中心
│ ├── pom.xml
│ └── src/main/
├── user-provider/ # 服务提供者(模拟用户服务)
│ ├── pom.xml
│ └── src/main/
└── user-consumer/ # 服务消费者(模拟订单服务,调用用户服务)
├── pom.xml
└── src/main/
3.1 父POM
父工程packaging设为pom,通过dependencyManagement统一管理SpringCloud版本:
xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.example</groupId>
<artifactId>eureka-demo</artifactId>
<version>1.0.0</version>
<packaging>pom</packaging>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.2.5.RELEASE</version>
<relativePath/>
</parent>
<properties>
<java.version>1.8</java.version>
<spring-cloud.version>Hoxton.SR3</spring-cloud.version>
</properties>
<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>
<modules>
<module>eureka-server</module>
<module>user-provider</module>
<module>user-consumer</module>
</modules>
</project>
⚠️ 版本对应关系一定要注意!SpringBoot和SpringCloud版本是绑定的,Hoxton对应SpringBoot 2.2.x/2.3.x,如果用错版本会出现各种莫名其妙的自动配置失效问题。
四、单节点Eureka Server
4.1 引入依赖
eureka-server模块只需要一个依赖:
xml
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
</dependency>
</dependencies>
很多教程会让你额外加spring-boot-starter-web,其实不用,点进eureka-server的依赖树看,它已经传递依赖了web模块。
4.2 启动类
启动类上加一个@EnableEurekaServer注解,就表示这是一个注册中心:
java
package com.example.eureka;
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);
}
}
这个注解做了什么呢?它会触发EurekaServerAutoConfiguration自动配置,帮我们启动一个Servlet容器,暴露一系列Eureka REST端点(比如/eureka/apps用于注册和发现服务),后台启动心跳检测、注册表缓存等定时任务。
4.3 application.yml配置
这是最关键的部分,单节点配置:
yaml
server:
port: 7900
spring:
application:
name: eureka-server
eureka:
instance:
hostname: localhost
client:
# 单机模式:当前服务就是Server,不需要把自己注册上去
register-with-eureka: false
# 单机模式:不需要从其他节点同步注册表
fetch-registry: false
service-url:
defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/
三个核心配置:
| 配置项 | 默认值 | 单机下为什么设false |
|---|---|---|
register-with-eureka |
true | 设为false表示"我自己就是注册中心,不用把我注册到别的注册中心" |
fetch-registry |
true | 设为false表示"我是单节点,不需要从其他Eureka节点拉取注册表" |
service-url.defaultZone |
- | Eureka Server的访问地址,Client就是通过这个地址和Server通信的 |
🔔 这里有个新手容易懵的点:defaultZone配置的是"你要和哪个Eureka Server通信"。对于单节点Server来说,它虽然不注册、不拉取,但配置里写自己的地址是因为Eureka内部有些逻辑需要知道自己的访问地址。
4.4 启动看效果
启动EurekaServerApplication,看到控制台输出Started EurekaServerApplication in X seconds就说明成功了。
浏览器访问 http://localhost:7900 ,能看到Eureka经典的浅绿色监控界面:
页面主要分几块:
- System Status:Eureka运行时信息,比如内存、启动时间、注册实例数
- DS Replicas:集群副本节点信息(单节点这里是空的)
- Instances currently registered with Eureka:已注册服务列表,现在是空的,因为还没有服务注册上来
- General Info:节点环境信息
- Instance Info:当前Eureka节点自身信息
这个界面虽然看起来比较复古,但功能很全,开发阶段经常需要刷新这里看服务注册情况。
五、注册一个服务提供者
现在我们写一个用户服务user-provider,把它注册到Eureka上。
5.1 依赖
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-client</artifactId>
</dependency>
</dependencies>
注意这里引入的是eureka-client,和server的依赖不一样。
5.2 启动类
java
package com.example.provider;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class UserProviderApplication {
public static void main(String[] args) {
SpringApplication.run(UserProviderApplication.class, args);
}
}
在较新版本的SpringCloud中,只要classpath下有eureka-client依赖,应用启动时会自动注册到Eureka,不需要再加@EnableEurekaClient注解。加了也不会报错,但属于冗余代码。
5.3 配置文件
yaml
server:
port: 8001
spring:
application:
# 这个name非常重要!服务调用方就是通过这个名字找到你的
name: user-provider
eureka:
client:
service-url:
# 告诉Client:Eureka Server地址在这里
defaultZone: http://localhost:7900/eureka/
instance:
# 实例ID:Eureka界面显示的名字,默认格式是 主机名:应用名:端口
instance-id: ${spring.cloud.client.ip-address}:${server.port}
# 注册时使用IP而不是主机名
prefer-ip-address: true
这里有两个配置我建议每个服务都加上:
prefer-ip-address: true:Eureka默认注册的是主机名,但很多环境下主机名无法解析(比如Docker容器里、没有配DNS的内网),直接用IP更稳妥。instance-id:自定义实例ID格式,默认会显示成电脑名:user-provider:8001,在控制台看多实例的时候不直观,改成IP:端口一目了然。
5.4 写个测试接口
java
package com.example.provider.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("/user")
public class UserController {
@Value("${server.port}")
private String port;
@GetMapping("/{id}")
public String getUserById(@PathVariable Long id) {
// 实际项目这里查数据库,我们简单模拟一下返回
return String.format("查询用户ID=%d,响应来自端口:%s", id, port);
}
}
5.5 验证注册
启动user-provider,注意看控制台日志,有这样一行就说明注册成功了:
DiscoveryClient_USER-PROVIDER/192.168.1.100:8001 - registration status: 204
返回204是HTTP状态码,表示注册成功但没有响应体,这是正常的。
这时候刷新Eureka控制台,在Instances currently registered with Eureka 下面就能看到USER-PROVIDER服务,状态是UP。
🔔 我刚学的时候遇到一个坑:服务启动日志显示204注册成功了,但Eureka界面上死活看不到。这是因为Eureka有响应缓存,默认30秒才刷新一次注册表缓存。开发时遇到这种情况别急,等半分钟或者重启Eureka试试,后面原理篇会讲这个缓存机制。
六、服务消费者通过服务名调用
再创建一个user-consumer(模拟订单服务),它从Eureka发现user-provider并调用。
6.1 依赖和启动类
依赖和provider一样,需要web和eureka-client。
启动类里需要配置一个RestTemplate,并加上@LoadBalanced注解:
java
package com.example.consumer;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.context.annotation.Bean;
import org.springframework.web.client.RestTemplate;
@SpringBootApplication
public class UserConsumerApplication {
public static void main(String[] args) {
SpringApplication.run(UserConsumerApplication.class, args);
}
@Bean
@LoadBalanced
public RestTemplate restTemplate() {
return new RestTemplate();
}
}
@LoadBalanced注解会给RestTemplate加一个拦截器,当你请求的URL里是服务名而不是IP时,拦截器会从Eureka本地缓存里找到实际的IP和端口,替换掉服务名再发请求,同时通过Ribbon做负载均衡。Ribbon后面会有专门一篇讲。
6.2 配置文件
yaml
server:
port: 8002
spring:
application:
name: user-consumer
eureka:
client:
service-url:
defaultZone: http://localhost:7900/eureka/
6.3 调用provider
写一个Controller测试:
java
package com.example.consumer.controller;
import org.springframework.beans.factory.annotation.Autowired;
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;
import org.springframework.web.client.RestTemplate;
@RestController
@RequestMapping("/order")
public class OrderController {
@Autowired
private RestTemplate restTemplate;
@GetMapping("/create/{userId}")
public String createOrder(@PathVariable Long userId) {
// 注意这里:URL里写的是服务名 user-provider,不是IP和端口!
String url = "http://user-provider/user/" + userId;
String userInfo = restTemplate.getForObject(url, String.class);
return "创建订单,关联用户信息:" + userInfo;
}
}
启动consumer,浏览器访问 http://localhost:8002/order/create/1 ,如果返回类似"创建订单,关联用户信息:查询用户ID=1,响应来自端口:8001",说明整个链路通了。
你可以把user-provider的端口改成8003,再启动一个实例(模拟多实例部署),多刷新几次consumer的接口,会发现返回的端口在8001和8003之间轮流切换,这就是Ribbon在做客户端负载均衡。
这一篇我们先不展开讲RestTemplate和Ribbon,后面有专门文章。这里你只需要有个直观感受:有了注册中心,调用方完全不需要知道服务部署在哪,只认服务名。
七、高可用集群搭建
单节点Eureka只适合开发测试,生产环境必须搭集群。为什么?注册中心是整个微服务体系的基础设施,一旦挂了:
- 已启动的服务因为本地有缓存,短期内还能互相调用
- 但新启动的服务无法注册,也无法拉取其他服务地址
- 故障服务无法被及时剔除,调用方可能调用到已经挂掉的实例
Eureka集群的实现思路非常简单:多个Eureka Server节点互相注册,节点之间通过"对等复制"(Peer-to-Peer)增量同步注册表。没有主从概念,每个节点地位平等,任何一个节点挂了,其他节点都有完整的注册表。
7.1 配置hosts
本地测试集群需要两个不同的主机名,不然Eureka会认为是同一个节点。
修改本机hosts文件:
- Mac/Linux:
/etc/hosts - Windows:
C:\Windows\System32\drivers\etc\hosts
添加:
127.0.0.1 eureka1.com
127.0.0.1 eureka2.com
为什么必须用不同的hostname?Eureka通过
eureka.instance.hostname来区分节点,如果两个节点用同一个hostname(哪怕端口不同),Eureka会认为它们是同一个节点,集群同步会出问题。生产环境机器名本身就不同,不用额外配。
7.2 用Profile配置双节点
我们不需要建两个工程,用SpringBoot的多Profile功能就能在本地启动两个实例。
application.yml(公共配置):
yaml
spring:
application:
name: eureka-server
eureka:
client:
# 集群模式下这两个保持默认true就好(默认就是true,可以不写)
register-with-eureka: true
fetch-registry: true
application-eureka1.yml(节点1):
yaml
server:
port: 7901
eureka:
instance:
hostname: eureka1.com
client:
service-url:
# 节点1把自己注册到节点2
defaultZone: http://eureka2.com:7902/eureka/
application-eureka2.yml(节点2):
yaml
server:
port: 7902
eureka:
instance:
hostname: eureka2.com
client:
service-url:
# 节点2把自己注册到节点1
defaultZone: http://eureka1.com:7901/eureka/
关键点就是节点1的defaultZone写节点2的地址,节点2的defaultZone写节点1的地址,这样它们就能互相发现、互相同步数据。
如果是3个节点,每个节点的defaultZone把另外两个都写上即可:
yaml
# eureka1的defaultZone
defaultZone: http://eureka2.com:7902/eureka/,http://eureka3.com:7903/eureka/
7.3 启动两个实例
IDEA里复制一份启动配置:
- Run/Debug Configurations → 选中EurekaServerApplication → 复制一份
- 第一份Program arguments填
--spring.profiles.active=eureka1 - 第二份填
--spring.profiles.active=eureka2
分别启动。
7.4 验证集群
分别访问 http://eureka1.com:7901 和 http://eureka2.com:7902:
- 在"DS Replicas"区域能看到对方节点
- 在"Instances currently registered with Eureka"里能看到两个Eureka节点都注册了
- 把user-provider注册到任意一个节点,刷新另一个节点也能看到这个服务(数据同步)
- 手动停掉任意一个节点,另一个还能正常提供服务
服务端注册到集群的话,defaultZone配置多个地址,用逗号分隔:
yaml
eureka:
client:
service-url:
defaultZone: http://eureka1.com:7901/eureka/,http://eureka2.com:7902/eureka/
Eureka Client会依次尝试列表中的地址,只要有一个注册成功就可以,节点之间会自动同步注册表,不用每个节点都注册一遍。
八、Actuator监控端点
SpringBoot Actuator提供了很多开箱即用的监控端点,和Eureka整合后可以查看注册状态、健康状况等,建议开发时都加上。
8.1 引入依赖
xml
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
8.2 暴露端点
SpringBoot 2.x出于安全考虑,默认只暴露/actuator/health和/actuator/info两个端点,其他都需要手动开启。开发阶段可以先全部打开:
yaml
management:
endpoints:
web:
exposure:
include: "*"
endpoint:
health:
show-details: always
shutdown:
enabled: true # 开启优雅关闭(POST请求 /actuator/shutdown)
几个和Eureka相关的常用端点:
| 端点路径 | 作用 |
|---|---|
GET /actuator/health |
应用健康状态,Eureka会通过这个判断服务是否UP |
GET /actuator/info |
应用自定义信息 |
GET /actuator/service-registry |
查看当前服务在Eureka的注册状态 |
GET /actuator/mappings |
查看所有URL映射 |
GET /actuator/beans |
查看Spring容器中的所有Bean |
GET /actuator/env |
查看环境变量和配置 |
POST /actuator/shutdown |
优雅关闭应用(生产环境不要开) |
⚠️ 生产环境千万别用
include: "*"把所有端点暴露出去,尤其是env、shutdown这些,会有安全风险。应该按需开放,或者结合Spring Security做鉴权。
九、我踩过的那些坑
这部分是我在实际开发中遇到的问题,新手很容易踩,建议收藏。
坑1:启动报错"Cannot execute request on any known server"
现象:Eureka Server启动时疯狂打印这个错误。
原因 :register-with-eureka和fetch-registry都是默认值true,但defaultZone地址不对或者目标Eureka没启动,Server自己作为Client尝试注册失败。
解决:单节点模式记得把这两个配置设为false;集群模式检查节点间地址是否能互通。
坑2:Eureka界面显示电脑名而不是IP
现象 :Eureka控制台Status列显示的是xxx-MacBook-Pro.local:user-provider:8001,调用方通过主机名访问失败。
解决:
yaml
eureka:
instance:
prefer-ip-address: true
instance-id: ${spring.cloud.client.ip-address}:${server.port}
坑3:服务都停了,Eureka界面还显示UP
现象:本地开发时服务停了,但Eureka界面上服务还在,要等好几分钟才消失。
原因 :这是Eureka的自我保护机制,默认开启。Eureka认为"短时间内心跳丢失比例过高可能是网络问题,不是服务真挂了",所以不会剔除实例,宁可保留也不误删。生产环境这是个好特性,但本地开发时会让我们误判。
本地开发可以临时关闭:
yaml
eureka:
server:
enable-self-preservation: false
eviction-interval-timer-in-ms: 3000
自我保护的原理我们下一篇原理篇会细讲。
坑4:多网卡/Docker环境注册了错误的IP
现象:服务器有Docker网卡、内网网卡、外网网卡,Eureka注册的IP是docker0或者127.0.0.1,其他服务调不通。
解决:手动指定使用的网段或者忽略的网卡:
yaml
spring:
cloud:
inetutils:
# 优先使用指定网段的IP
preferred-networks:
- 192.168.1
- 10.0.0
# 忽略指定网卡
ignored-interfaces:
- docker0
- veth.*
- lo
坑5:注册成功了,但调用时报"I/O error on GET request"
现象:Eureka界面能看到服务,但RestTemplate调用失败。
排查思路:
- 先看Eureka上注册的IP和端口对不对,直接用postman调一下那个地址能不能通
- 检查服务器防火墙/安全组有没有开放服务端口
- 检查服务有没有context-path(比如server.servlet.context-path=/api),如果有,调用时URL里也要带上
- 看是不是Ribbon超时时间太短(默认1秒),服务启动慢或者网络慢时会超时
十、高频面试题
1. Eureka的工作流程/原理是什么?
分Server和Client两部分。
- 服务启动时Eureka Client向Server注册自己的元数据(服务名、IP、端口等)
- Client每隔30秒发送一次心跳续约
- Server默认90秒收不到心跳,将该实例从注册表剔除
- Client每隔30秒从Server拉取最新注册表缓存到本地
- 服务调用时直接用本地缓存的地址,通过服务名找到目标实例
- Eureka Server节点之间通过P2P方式增量同步注册表,无主从之分
2. Eureka和Zookeeper的区别?为什么Eureka更适合做注册中心?(CAP)
这是经典的CAP理论应用题:
- Eureka是AP架构,优先保证可用性。Eureka节点是对等的,少数节点挂了不影响其他节点提供服务,即使数据可能不是最新的。注册中心场景下,可用性比强一致性更重要------即使拿到的服务列表有个别过期实例,调用方还有重试/熔断机制,比整个注册中心不可用强。
- Zookeeper是CP架构 ,优先保证一致性。Zookeeper用ZAB协议,当Leader挂了选举期间整个集群不可用(可能长达几十秒),这期间注册服务和发现服务都会失败。
所以在微服务注册中心场景下,Eureka(以及后来的Nacos)比Zookeeper更合适。
3. Eureka集群为什么要互相注册?
Eureka集群没有主从概念,所有节点都是对等的(Peer)。服务只需要注册到任意一个节点,节点之间会通过对等复制把注册信息同步给其他节点。互相注册是为了让节点之间知道彼此的存在,从而进行注册表的增量同步。如果不互相注册,每个节点都是孤岛,数据无法同步。
总结
这篇文章我们从0开始:
- 理解了注册中心解决的问题------服务地址动态管理
- 搭建了单节点Eureka Server
- 注册了服务提供者,并用服务消费者通过服务名完成调用
- 搭建了Eureka双节点高可用集群
- 整合了Actuator监控端点
- 总结了5个常见坑和解决方案
- 分析了3道高频面试题
到这里你应该已经能跑通一个最基础的微服务环境了。但Eureka的内容还没完,下一篇我们会深挖Eureka的核心原理:自我保护机制、健康检查、Eureka REST API、注册表缓存、与Nacos的对比等。
写作不易,如果这篇文章对你有帮助,欢迎点赞收藏,你的支持是我持续更新的动力。
你在搭建Eureka时还遇到过什么其他问题?欢迎在评论区留言交流。