【SpringCloud】Eureka、Nacos 简单概念笔记

Eureka、Nacos

版本说明:本文以 Spring Boot 3 / Spring Cloud 新版本思路为主。很多旧教程会使用 bootstrap.yml、Ribbon 等写法,学习时可以看,但自己写新项目时更建议优先使用 Spring Cloud LoadBalancer、spring.config.import 等新写法。


1. 微服务里的几个核心问题

单体项目里,前端请求通常直接打到一个后端服务:
浏览器/客户端
单体后端应用
数据库

微服务项目拆分后,系统可能变成这样:
浏览器/客户端
Gateway 网关
用户服务 user-service
订单服务 order-service
商品服务 product-service
用户库
订单库
商品库

拆分之后会出现几个新问题:

  • 服务越来越多,调用方怎么知道某个服务现在在哪台机器、哪个端口?
  • 同一个服务可能部署多个实例,请求应该打到哪一个实例?
  • 服务上线、下线、宕机后,调用方如何及时感知?
  • 公共认证、日志、限流、跨域等逻辑放在哪里更合适?
  • 多个服务的配置如何统一管理、动态刷新?

对应到 Spring Cloud 生态中,常见组件分工如下:

问题 典型组件 作用
服务在哪里 Eureka / Nacos Discovery 服务注册与服务发现
多实例怎么选 Spring Cloud LoadBalancer / Nacos 权重 客户端负载均衡
服务之间怎么调用 OpenFeign 声明式 HTTP 远程调用
外部请求从哪里进 Spring Cloud Gateway API 网关、统一入口
配置怎么统一管 Nacos Config / Spring Cloud Config 配置中心、动态配置

服务启动后注册到注册中心;调用方从注册中心发现目标服务实例;负载均衡器从多个实例中选一个;OpenFeign 发起服务间调用;Gateway 负责外部入口和公共过滤逻辑;Nacos 还可以统一管理配置。


2. Eureka:注册中心、服务注册与服务发现

2.1 Eureka 是什么

Eureka 是 Netflix OSS 体系里的服务注册与发现组件。它主要分成两类角色:

  • Eureka Server:注册中心,负责保存服务实例信息。
  • Eureka Client:微服务应用,启动后把自己注册到 Eureka Server,也可以从 Eureka Server 获取其他服务列表。

可以把 Eureka Server 理解成一个"服务通讯录"其他服务调用 user-service 时,不需要写死 IP 和端口,只需要通过服务名去查。

2.2 服务注册

服务注册指的是:服务启动后,把自己的服务名、IP、端口、健康状态等信息上报给注册中心。

user-service 为例,它启动时会把自己注册进去:

yaml 复制代码
server:
  port: 8081

spring:
  application:
    name: user-service

eureka:
  client:
    service-url:
      defaultZone: http://localhost:8761/eureka/

spring.application.name 很关键,它就是服务名。服务之间一般不是通过 localhost:8081 调用,而是通过 user-service 这个逻辑名称调用。

2.3 服务发现

服务发现指的是:调用方根据服务名,从注册中心拿到目标服务的实例列表。

例如 order-service 想调用 user-service,它不需要知道 user-service 部署在哪,只需要知道服务名:

text 复制代码
order-service -> 注册中心 -> 查询 user-service -> 得到实例列表 -> 选择一个实例调用

如果 user-service 有多个实例:

text 复制代码
user-service
├── 192.168.1.10:8081
├── 192.168.1.11:8081
└── 192.168.1.12:8081

注册中心会保存这些实例,调用方再结合负载均衡策略选择一个。

2.4 Eureka 简单部署流程

第一步:创建 Eureka Server

依赖示例:

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

启动类:

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

配置文件:

yaml 复制代码
server:
  port: 8761

spring:
  application:
    name: eureka-server

eureka:
  client:
    register-with-eureka: false
    fetch-registry: false
    service-url:
      defaultZone: http://localhost:8761/eureka/

这里的两个配置需要注意:

  • register-with-eureka: false:Eureka Server 不把自己当作普通服务注册。
  • fetch-registry: false:Eureka Server 不需要从自己这里拉取服务列表。

启动后访问:

text 复制代码
http://localhost:8761

可以看到 Eureka 控制台。

第二步:创建服务提供者 user-service

依赖示例:

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

配置文件:

yaml 复制代码
server:
  port: 8081

spring:
  application:
    name: user-service

eureka:
  client:
    service-url:
      defaultZone: http://localhost:8761/eureka/

简单接口:

java 复制代码
@RestController
@RequestMapping("/users")
public class UserController {

    @GetMapping("/{id}")
    public String getUser(@PathVariable Long id) {
        return "user id = " + id;
    }
}

启动后,Eureka 控制台中会出现 USER-SERVICE

第三步:创建服务消费者 order-service
yaml 复制代码
server:
  port: 8082

spring:
  application:
    name: order-service

eureka:
  client:
    service-url:
      defaultZone: http://localhost:8761/eureka/

后面可以通过 OpenFeign 或 RestTemplate 调用 user-service


3. 负载均衡:为什么不能只调用一个实例

3.1 负载均衡解决什么问题

当一个服务部署多个实例时,请求不能永远打到同一个实例,否则会导致:

  • 某台机器压力过大;
  • 其他实例空闲浪费;
  • 单个实例宕机后请求失败;
  • 系统整体吞吐量上不去。

负载均衡就是在多个实例中选择一个实例来处理请求。

3.2 服务名调用与负载均衡

以前很多教程会讲 Ribbon,现在新版本更推荐 Spring Cloud LoadBalancer。

服务调用时通常不是这样写:

text 复制代码
http://localhost:8081/users/1

而是这样写:

text 复制代码
http://user-service/users/1

这里的 user-service 不是域名,而是注册中心中的服务名。调用流程大致是:

  1. 先根据 user-service 去注册中心拉取实例列表;
  2. 负载均衡器从列表里选一个实例;
  3. http://user-service/users/1 转成类似 http://192.168.1.10:8081/users/1
  4. 最后发起真正的 HTTP 请求。

3.3 常见负载均衡策略

常见策略包括:

  • 轮询:第 1 次打实例 A,第 2 次打实例 B,第 3 次打实例 C,然后循环。
  • 随机:随机选择一个实例。
  • 权重:权重越高,被选中的概率越大。
  • 同集群优先:消费者优先调用同一个集群或同一个机房内的服务实例。

4. Nacos:注册中心 + 配置中心

4.1 Nacos 是什么

Nacos 是阿里开源的动态服务发现、配置管理和服务管理平台。在 Spring Cloud Alibaba 体系中,Nacos 通常承担两个角色:

  • Nacos Discovery:服务注册与发现,类似 Eureka。
  • Nacos Config:配置中心,集中管理应用配置,支持动态刷新。

所以 Nacos 比 Eureka 的能力更综合。Eureka 主要关注服务注册发现,而 Nacos 同时可以做注册中心和配置中心。

4.2 Nacos 服务注册与发现

服务启动后,将自己注册到 Nacos:

yaml 复制代码
server:
  port: 8081

spring:
  application:
    name: user-service
  cloud:
    nacos:
      discovery:
        server-addr: 127.0.0.1:8848

启动多个服务后,可以在 Nacos 控制台看到服务列表。

Nacos 控制台默认地址通常是:

text 复制代码
http://localhost:8848/nacos

常见默认账号密码是:

text 复制代码
nacos / nacos

具体以你本地安装版本为准。

4.3 服务下线

服务下线有两种理解:

一种是应用真正停止 。例如你关闭了某个 user-service 实例。注册中心会通过心跳或健康检查发现它不可用,然后把它从可用列表中剔除或标记异常。

另一种是手动下线实例。在 Nacos 控制台中可以把某个实例临时下线。这样它虽然进程还在,但消费者不会再优先调用它。

典型使用场景:

  • 服务要灰度发布,先下线旧实例;
  • 某台机器异常,先摘掉流量;
  • 临时维护,不希望继续接收请求。

理解重点:

下线不是删除服务,而是让该实例暂时不参与调用。

4.4 权重配置

Nacos 支持给实例设置权重。权重越高,被调用的概率越大。

例如:

text 复制代码
user-service 实例 A:权重 1
user-service 实例 B:权重 5

如果负载均衡策略使用权重,实例 B 大约会获得更多流量。

配置示例:

yaml 复制代码
spring:
  cloud:
    nacos:
      discovery:
        server-addr: 127.0.0.1:8848
        weight: 5

权重常用于:

  • 新版本灰度发布:新版本先给较小权重,观察稳定后再逐步提高;
  • 机器性能不同:高配置机器设置更高权重;
  • 临时降流量:把某个实例权重调低。

少量流量
更多流量
consumer
Nacos + LoadBalancer
user-service v1 / weight=1
user-service v2 / weight=5

4.5 同集群优先

同集群优先的意思是:消费者优先调用与自己处在同一集群、同一机房或同一区域的服务实例。

例如:

text 复制代码
上海集群:user-service A、order-service A
北京集群:user-service B、order-service B

上海的 order-service 优先调用上海的 user-service,北京的 order-service 优先调用北京的 user-service

这个做的好处是网络延迟更低、跨机房调用更少,速度更加快。还有就是一个集群故障时,可以再考虑降级调用其他集群。

配置示例:

yaml 复制代码
spring:
  cloud:
    nacos:
      discovery:
        cluster-name: SHANGHAI

如果要让 Spring Cloud LoadBalancer 更好地结合 Nacos 的集群信息,需要根据项目版本启用对应的 Nacos LoadBalancer 集成配置,例如:

yaml 复制代码
spring:
  cloud:
    loadbalancer:
      nacos:
        enabled: true

权重解决"谁多接一点流量",集群优先解决"尽量调用离我近的服务"。

4.6 环境隔离:Namespace、Group、DataId

Nacos 里常见的隔离概念有三个:

概念 用途 类比
Namespace 环境级隔离 dev、test、prod 三个空间
Group 分组隔离 同一环境下按业务线或项目分组
DataId 配置文件标识 user-service-dev.yml

最常用的是 Namespace。比如你可以创建三个命名空间:

text 复制代码
dev      开发环境
test     测试环境
prod     生产环境

这样开发环境的服务和配置不会误连到生产环境。

示例:

yaml 复制代码
spring:
  cloud:
    nacos:
      discovery:
        namespace: dev-namespace-id
      config:
        namespace: dev-namespace-id

注意:namespace 配的通常不是命名空间名称,而是命名空间 ID。

4.7 Nacos 配置中心

配置中心的价值是:把配置从代码包里抽出来,集中放到 Nacos 管理。

以前配置可能写在每个服务自己的 application.yml 中:

用了 Nacos Config 后,可以把这些配置放在 Nacos 控制台中。应用启动时从 Nacos 拉取配置,运行中还可以监听配置变化。
Nacos Config user-service Nacos Config user-service 启动时拉取 user-service-dev.yml 返回配置内容 使用配置启动 配置变化通知 动态刷新部分配置

现代写法示例:

yaml 复制代码
spring:
  application:
    name: user-service
  cloud:
    nacos:
      config:
        server-addr: 127.0.0.1:8848
        group: DEFAULT_GROUP
        file-extension: yaml
  config:
    import:
      - optional:nacos:user-service-dev.yaml

如果使用动态刷新,可以配合 @RefreshScope,这就支持不用重新启动服务即可更改配置:

java 复制代码
@RestController
@RefreshScope
public class ConfigController {

    @Value("${user.level:normal}")
    private String userLevel;

    @GetMapping("/config/user-level")
    public String getUserLevel() {
        return userLevel;
    }
}

在 Nacos 控制台修改配置后,接口返回值可以随配置变化而变化。

4.8 Nacos 简单部署流程

第一步:启动 Nacos Server

学习环境可以直接本地启动 Nacos 单机版,常见端口是8848

启动成功后访问:

text 复制代码
http://localhost:8848/nacos
第二步:服务接入 Nacos Discovery

添加依赖:

xml 复制代码
<dependency>
    <groupId>com.alibaba.cloud</groupId>
    <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>

配置:

yaml 复制代码
server:
  port: 8081

spring:
  application:
    name: user-service
  cloud:
    nacos:
      discovery:
        server-addr: 127.0.0.1:8848

启动后在控制台查看服务列表。

第三步:服务接入 Nacos Config

添加依赖:

xml 复制代码
<dependency>
    <groupId>com.alibaba.cloud</groupId>
    <artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
</dependency>

配置:

yaml 复制代码
spring:
  application:
    name: user-service
  cloud:
    nacos:
      config:
        server-addr: 127.0.0.1:8848
        file-extension: yaml
  config:
    import:
      - optional:nacos:user-service-dev.yaml

然后在 Nacos 控制台新建配置:

text 复制代码
Data ID: user-service-dev.yaml
Group: DEFAULT_GROUP
配置格式: YAML

配置内容示例:

yaml 复制代码
user:
  level: vip
第四步:多环境隔离

创建命名空间:

text 复制代码
dev
prod

然后在服务配置中指定命名空间 ID:

yaml 复制代码
spring:
  cloud:
    nacos:
      discovery:
        namespace: dev-namespace-id
      config:
        namespace: dev-namespace-id

这样开发环境服务只注册到开发环境空间,开发环境配置也只从开发空间读取。


5. Eureka 与 Nacos 的区别

对比项 Eureka Nacos
定位 服务注册与发现 服务注册发现 + 配置中心 + 服务管理
生态 Netflix OSS / Spring Cloud Netflix Spring Cloud Alibaba / Nacos 生态
配置中心 不提供,需要搭配其他组件 原生支持配置中心
控制台能力 相对简单,主要查看服务实例 更丰富,可管理服务、实例、权重、配置、命名空间等
权重配置 原生能力弱,通常依赖负载均衡策略扩展 原生支持实例权重
环境隔离 通常靠不同注册中心或配置区分 支持 Namespace、Group 等隔离方式
服务下线 更多依赖心跳和实例状态 控制台可更方便地下线实例、调整权重
适合场景 学习注册中心原理、传统 Spring Cloud 项目 国内项目常见,适合注册中心和配置中心统一管理

希望对你有所帮助~~

相关推荐
LuminousCPP1 小时前
C 语言动态内存管理全解析:从基础函数到柔性数组与内存分区
c语言·经验分享·笔记·学习·柔性数组
d111111111d2 小时前
MQTT+STM32+ESP8266网络程序分层+韦老师
笔记·stm32·单片机·嵌入式硬件·学习·php
Devin~Y2 小时前
大厂Java面试实战:Spring Boot/Cloud、Redis/Kafka、JVM调优与Spring AI RAG(内容社区UGC+AIGC客服场景)
java·jvm·spring boot·redis·spring cloud·kafka·mybatis
文慧的科技江湖2 小时前
零碳园区综合管理平台PRD需求文档 - 慧知开源充电桩平台
spring cloud·微服务·开源·能源·慧知开源光储充管理平台·慧知开源光储充管理系统·零碳园区管理平台
得闲喝茶2 小时前
SQL处理数据的常用语法语句
数据库·笔记·sql·数据分析·excel
糖炒栗子03262 小时前
最小二乘优化笔记:从损失函数、正则项到 BA / 图优化
人工智能·笔记·机器学习
nnsix2 小时前
Unity HybridCLR 笔记
笔记·unity·游戏引擎
sbjdhjd3 小时前
Docker 网络工业级实战手册
linux·运维·经验分享·笔记·docker·云原生·云计算
Flittly3 小时前
【日常小问】解决 Jenkins 部署 Spring Cloud 微服务到 Docker 容器启动失败的问题
运维·笔记·docker·微服务·jenkins