SpringCloud Alibaba 核心组件解析:服务注册与发现(Nacos)

SpringCloud Alibaba 核心组件解析:服务注册与发现(Nacos)

技术栈 :Spring Boot 3.2.0 + Spring Cloud 2023.0.0 + Spring Cloud Alibaba 2023.0.0.0-RC1 + Nacos


1.1 是什么 --- Nacos 定位与核心能力

1.1.1 一句话定义

Nacos(Dynamic Na ming and Co nfiguration S ervice)= 注册中心 + 配置中心 的二合一解决方案。

1.1.2 生活化类比:公司前台 + 公告栏

复制代码
┌─────────────────────────────────┐
│            Nacos                 │
│                                 │
│  ┌─────────┐   ┌─────────────┐ │
│  │ 注册中心  │   │  配置中心    │ │
│  │ (前台)   │   │  (公告栏)    │ │
│  │         │   │             │ │
│  │ 员工报到  │   │ 公司通知    │ │
│  │ 离职注销  │   │ 配置变更    │ │
│  │ 查同事    │   │ 大家看到    │ │
│  └─────────┘   └─────────────┘ │
└─────────────────────────────────┘
  • 注册中心 = 前台:新员工入职登记、离职注销、查某人在哪个工位
  • 配置中心 = 公告栏:公司通知张贴在公告栏,所有人实时看到更新

1.1.3 阿里内部验证

Nacos 在阿里巴巴内部经过双十一核心链路 验证,管理着超过 10 万+ 服务实例,是阿里云微服务引擎 MSE 的核心组件。


1.2 为什么 --- Nacos 相比 Eureka/Consul 的优势

1.2.1 一站式 vs 多组件

复制代码
Eureka : 仅注册中心
Consul : 注册中心 + KV配置
Nacos  : 注册中心 + 配置中心(功能完整,自带管理控制台)

1.2.2 AP + CP 可切换

复制代码
其他注册中心:
  Eureka  = 纯 AP(高可用,可能拿到过期数据)
  Consul  = 纯 CP(强一致,选主期间不可用)
  ZK      = 纯 CP

Nacos:
  AP 模式(默认)→ 适合互联网高并发场景
  CP 模式         → 适合金融/支付强一致场景
  → 一个组件适配两种需求!

1.2.3 功能对比表

维度 Nacos Consul Eureka
CAP 模型 AP + CP 可切换 CP AP
一致性协议 Raft(CP) + Distro(AP) Raft ---
配置中心 ✅ 完整 ✅ KV 存储
动态刷新 @RefreshScope @RefreshScope
控制台 ✅ 功能强大 ✅ 较基础 ✅ 基础
权重/元数据
多数据中心
运维复杂度
阿里生态整合 ✅ 原生(Sentinel/Seata/RocketMQ)

1.3 怎么做 --- Nacos 完整实战

1.3.1 启动 Nacos Server

bash 复制代码
# Windows 单机模式
startup.cmd -m standalone

# Linux/Mac
sh startup.sh -m standalone

# 访问控制台:http://localhost:8848/nacos
# 默认账号/密码:nacos/nacos

1.3.2 项目模块

模块 端口 角色
cloudalibaba-provider-payment9001 9001 Provider(注册到 Nacos)
cloudalibaba-consumer-nacos-order83 83 Consumer(从 Nacos 发现服务)

1.3.3 步骤 ①:引入依赖

xml 复制代码
<dependency>
    <groupId>com.alibaba.cloud</groupId>
    <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
<!-- 如需配置中心功能,额外引入: -->
<dependency>
    <groupId>com.alibaba.cloud</groupId>
    <artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
</dependency>

1.3.4 步骤 ②:Provider 配置

yaml 复制代码
server:
  port: 9001

spring:
  application:
    name: nacos-payment-provider   # 服务名(注册到 Nacos 用的名字)
  cloud:
    nacos:
      discovery:
        server-addr: localhost:8848  # Nacos Server 地址
    sentinel:
      transport:
        dashboard: localhost:8080
        port: 8719

1.3.5 步骤 ③:Provider 启动类

java 复制代码
@SpringBootApplication
@EnableDiscoveryClient    // ← 通用服务发现注解
public class Main9001 {
    public static void main(String[] args) {
        SpringApplication.run(Main9001.class, args);
    }
}

1.3.6 步骤 ④:Provider Controller

java 复制代码
@RestController
public class PayAlibabaController {

    @Value("${server.port}")
    private String serverPort;

    @GetMapping(value = "/pay/nacos/{id}")
    public String getPayInfo(@PathVariable("id") Integer id) {
        return "nacos registry, serverPort: " + serverPort + "\t id" + id;
    }

    // Sentinel 保护的接口(同时用于 Feign 调用)
    @GetMapping("/pay/nacos/get/{orderNo}")
    @SentinelResource(value = "getPayByOrderNo",
                      blockHandler = "handlerBlockHandler")
    public ResultData getPayByOrderNo(@PathVariable("orderNo") String orderNo) {
        PayDTO payDTO = new PayDTO();
        payDTO.setId(1024);
        payDTO.setOrderNo(orderNo);
        payDTO.setAmount(BigDecimal.valueOf(9.9));
        payDTO.setPayNo("pay:" + IdUtil.fastUUID());
        payDTO.setUserId(1);
        return ResultData.success("查询返回值:" + payDTO);
    }

    // Sentinel 流控的 fallback
    public ResultData handlerBlockHandler(@PathVariable("orderNo") String orderNo,
                                           BlockException exception) {
        return ResultData.fail(ReturnCodeEnum.RC500.getCode(),
            "getPayByOrderNo服务不可用,触发sentinel流控配置规则");
    }
}

1.3.7 步骤 ⑤:Consumer 配置

yaml 复制代码
server:
  port: 83

spring:
  application:
    name: nacos-order-consumer
  cloud:
    nacos:
      discovery:
        server-addr: localhost:8848
    sentinel:
      log:
        dir: D:/yangnan/Documents/SpringCloud/sentinel-log

# Provider 的服务名
service-url:
  nacos-user-service: http://nacos-payment-provider

# 激活 Sentinel 对 Feign 的支持
feign:
  sentinel:
    enabled: true

1.3.8 步骤 ⑥:Consumer RestTemplate + Feign 混合调用

java 复制代码
@RestController
public class OrderNacosController {

    @Resource
    private RestTemplate restTemplate;

    @Value("${service-url.nacos-user-service}")
    private String serverURL;  // http://nacos-payment-provider

    // RestTemplate 方式
    @GetMapping("/consumer/pay/nacos/{id}")
    public String paymentInfo(@PathVariable("id") Integer id) {
        return restTemplate.getForObject(serverURL + "/pay/nacos/" + id,
            String.class) + "\t 我是OrderNacosController83调用者";
    }

    // Feign + Sentinel 方式
    @Resource
    private PayFeignSentinelApi payFeignSentinelApi;

    @GetMapping(value = "/consumer/pay/nacos/get/{orderNo}")
    public ResultData getPayByOrderNo(@PathVariable("orderNo") String orderNo) {
        return payFeignSentinelApi.getPayByOrderNo(orderNo);
    }
}

1.3.9 验证

  1. 启动 Nacos → Provider(9001) → Consumer(83)
  2. 打开 http://localhost:8848/nacos → 服务列表 → 看到 nacos-payment-providernacos-order-consumer
  3. 访问 http://localhost:83/consumer/pay/nacos/1 → 返回 Provider 的端口号

1.4 深入原理 --- Nacos AP + CP 切换

1.4.1 架构

复制代码
Nacos Server 集群
┌──────────────────────────────┐
│  Leader (Raft 选主)          │ ← CP 模式(配置数据)
│  → 配置数据一致性由 Raft 保证  │
├──────────────────────────────┤
│  全部节点                     │ ← AP 模式(服务数据)
│  → 服务数据用 Distro 协议同步 │
└──────────────────────────────┘

1.4.2 持久化

Nacos 默认使用内嵌 Derby 数据库,生产环境需切换到 MySQL:

properties 复制代码
# nacos/conf/application.properties
spring.datasource.platform=mysql
db.num=1
db.url.0=jdbc:mysql://localhost:3306/nacos_config?characterEncoding=utf8&connectTimeout=1000&socketTimeout=3000&autoReconnect=true
db.user=root
db.password=123456

1.5 Nacos vs Consul 配置对比

配置项 Nacos Consul
注册中心注解 @EnableDiscoveryClient @EnableDiscoveryClient
注册地址 spring.cloud.nacos.discovery.server-addr spring.cloud.consul.host + port
服务名 spring.application.name spring.application.name
控制台 http://localhost:8848/nacos http://localhost:8500
配置中心注解 @RefreshScope(同) @RefreshScope(同)

1.6 面试题

Q1:Nacos 如何实现 AP 和 CP 的切换?

:Nacos 对于临时实例ephemeral: true,默认)使用自研的 Distro 协议保证 AP;对于持久化实例ephemeral: false)使用 Raft 协议保证 CP。配置数据始终使用 CP 模式。通过在客户端配置 spring.cloud.nacos.discovery.ephemeral=false 切换。

Q2:Nacos 和 Eureka 的核心区别?

  1. Nacos = 注册中心 + 配置中心,Eureka 仅是注册中心
  2. Nacos 支持 AP/CP 切换,Eureka 只能是 AP
  3. Nacos 使用 Netty 长连接 + HTTP 两种通信方式,Eureka 仅 HTTP
  4. Nacos 有完善的权重/元数据/分组/命名空间机制

1.7 踩坑指南

现象 原因 解决
🔴 Nacos 连接不上 Connection refused Nacos Server 未启动或端口错误 确认 startup.cmd -m standalone
🔴 服务名不对 UnknownHostException Consumer 填写的服务名与 Provider 的 spring.application.name 不一致 严格保持一致
🔴 Nacos 控制台看不到服务 注册失败 未引入 @EnableDiscoveryClient 检查启动类注解
🔴 版本冲突 启动报错 Spring Cloud Alibaba 版本与 Spring Boot/Cloud 版本不兼容 查阅版本对应表

1.8 章节总结

要点 说明
Nacos = 注册中心 + 配置中心 一个组件替代 Eureka + Config
AP + CP 可切换 默认 AP(Distro),配置 ephemeral=false 切换 CP(Raft)
阿里验证 双十一核心链路,10 万+ 实例
关键注解 @EnableDiscoveryClient(通用)+ @RefreshScope
关键配置 spring.cloud.nacos.discovery.server-addr: localhost:8848
生产建议 持久化切换到 MySQL,集群部署至少 3 节点
相关推荐
兰令水2 小时前
leecodecode【单调栈】【2026.6.12打卡-java版本】
java·开发语言·算法
云烟成雨TD2 小时前
Agent Scope Java 2.x 系列【8】工具调用
java·人工智能·agent
AI人工智能+电脑小能手2 小时前
【大白话说Java面试题 第112题】【并发篇】第12题:AQS 中节点的入队时机有哪些?
java·开发语言·面试
摇滚侠2 小时前
SpringMVC 入门到实战 处理静态资源的过程 64
java·后端·spring·maven·intellij-idea
影寂ldy2 小时前
C# 泛型委托
java·算法·c#
摇滚侠2 小时前
MyBatis 入门到项目实战 MyBatis 核心配置文件 15-19
java·tomcat·mybatis
IT WorryFree2 小时前
Zabbix 7.4 API 可同步全量参数清单(同步第三方系统专用)
java·开发语言·zabbix
RoboWizard2 小时前
一块硬盘上架前要闯多少关?
java·服务器·数据库
Liquad Li2 小时前
ABP vNext 标准分层解决方案项目结构完整解析
后端