Skip to content

Nacos 学习指南

导航目录

一、Nacos 概述与核心能力

1.1 什么是 Nacos

Nacos 全称是 Dynamic Naming and Configuration Service,是阿里开源的动态服务发现、配置管理和服务治理平台。

  • Na 代表 Naming,服务注册与发现
  • co 代表 Configuration,统一配置管理
  • s 代表 Service,服务能力与服务治理

1.2 Nacos 能解决什么问题

在微服务架构里,服务数量一旦变多,就会出现下面这些问题:

  • 服务地址频繁变化,调用方不知道该连谁
  • 配置文件分散在多个项目里,修改配置容易漏改
  • 环境多,开发、测试、预发、生产配置容易串
  • 服务上下线频繁,需要自动感知实例变化
  • 灰度发布、权重路由、集群隔离需要统一治理能力

Nacos 就是为了解决这些问题而生。

重点:Nacos 最核心的两个能力就是 服务注册发现统一配置管理

1.3 Nacos 的核心功能

1.3.1 服务注册与发现

  • 服务启动时向 Nacos 注册自己的实例信息
  • 消费者从 Nacos 获取可用服务列表
  • 支持临时实例和持久化实例
  • 支持健康检查、权重、集群、元数据

1.3.2 配置中心

  • 统一管理配置
  • 支持配置实时推送
  • 支持按环境隔离
  • 支持命名空间、分组、Data ID 管理

1.3.3 服务治理

  • 支持健康检查
  • 支持实例上下线
  • 支持权重路由
  • 支持集群路由
  • 支持元数据扩展

1.4 Nacos 和 Eureka、Consul、Apollo 的区别

对比项NacosEurekaConsulApollo
注册中心支持支持支持不擅长
配置中心支持不支持一般
服务健康检查支持支持支持不涉及
DNS/HTTP 接口支持HTTPDNS/HTTPHTTP
控制台支持一般支持支持
与 Spring Cloud Alibaba 集成非常好一般一般一般

1.5 Nacos 核心概念

1.5.1 Namespace

  • 用于环境隔离
  • 常见划分:devtestprod

1.5.2 Group

  • 用于服务或配置分组
  • 常见分组:DEFAULT_GROUPORDER_GROUP

1.5.3 Service

  • 服务名,通常对应一个微服务应用

1.5.4 Instance

  • 服务实例,具体到某个 IP 和端口

1.5.5 Data ID

  • 配置项的唯一标识
  • 常见形式:user-service.yaml

1.6 Namespace、Group、Data ID 的职责边界

这三个概念很容易混淆,实际项目中建议这样理解:

维度作用常见值是否建议频繁创建
Namespace环境隔离devtestprod不建议
Group业务分类DEFAULT_GROUPORDER_GROUP适度
Data ID具体配置文件标识order-service.yaml经常使用

可以记成一句话:

  • Namespace 解决环境问题
  • Group 解决业务归类问题
  • Data ID 解决具体配置文件定位问题

1.7 注册中心和配置中心中的三个维度

在 Nacos 里,注册中心和配置中心都能使用 NamespaceGroup,但使用侧重点不同:

  • 注册中心里,Namespace 常用来隔离环境,Group 常用来隔离业务服务
  • 配置中心里,Namespace 常用来隔离环境,Group 常用来隔离配置类别或业务线
  • Data ID 只在配置中心里出现,不用于服务注册

1.8 Nacos 架构模型

text
服务提供者 -> 注册实例到 Nacos
服务消费者 -> 从 Nacos 订阅服务列表
配置发布者 -> 发布配置到 Nacos
业务应用 -> 监听配置变更并动态刷新

1.9 Nacos 典型使用场景

  • Spring Cloud 微服务注册中心
  • 多环境配置中心
  • 动态开关配置
  • 灰度发布和服务流量治理
  • 多机房、多集群服务管理

二、Nacos 环境安装与启动

2.1 版本选择建议

  • 学习阶段可直接使用单机版
  • 生产环境建议使用稳定版本并结合 MySQL 部署集群
  • Spring Cloud Alibaba 项目要注意与 Spring Boot、Spring Cloud 的版本兼容

重点:实际项目里,版本兼容往往比功能本身更容易踩坑。

2.2 单机安装

2.2.1 下载与解压

bash
# 下载指定版本的 Nacos 安装包
wget https://github.com/alibaba/nacos/releases/download/2.3.2/nacos-server-2.3.2.tar.gz
# 解压安装包
tar -zxvf nacos-server-2.3.2.tar.gz
# 进入启动脚本目录
cd nacos/bin

2.2.2 单机启动

Linux / Mac:

bash
# `-m standalone` 表示以单机模式启动,适合本地开发和学习
sh startup.sh -m standalone

Windows:

bash
# Windows 下同样使用 standalone 单机模式
startup.cmd -m standalone

2.2.3 访问控制台

  • 默认地址:http://127.0.0.1:8848/nacos
  • 默认账号密码通常为:nacos / nacos

2.3 常用启动命令

bash
# 单机模式
sh startup.sh -m standalone

# 集群模式
# 不加 `-m standalone` 时通常按集群模式启动
sh startup.sh

# 停止服务
sh shutdown.sh

2.4 单机模式和集群模式区别

  • 单机模式适合学习和本地开发
  • 集群模式适合生产环境
  • 集群模式通常需要 MySQL 持久化配置数据

2.5 Nacos 常用端口

  • 8848:Web 控制台和 OpenAPI 默认端口
  • 9848:客户端 gRPC 通信端口
  • 9849:服务端之间 gRPC 通信端口

2.6 使用 MySQL 持久化配置数据

2.6.1 创建数据库

sql
-- 创建 Nacos 配置持久化数据库
CREATE DATABASE nacos_config DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;

2.6.2 导入初始化脚本

Nacos 安装目录中通常自带初始化 SQL,例如:

bash
# 将 Nacos 官方提供的初始化表结构导入到 nacos_config 数据库
mysql -uroot -p nacos_config < nacos-mysql.sql

2.6.3 修改配置文件

conf/application.properties

properties
# 指定底层使用 mysql 持久化配置数据
spring.sql.init.platform=mysql

# 当前数据库实例数量,单库时通常为 1
db.num=1
# Nacos 配置库连接地址
db.url.0=jdbc:mysql://127.0.0.1:3306/nacos_config?characterEncoding=utf8&connectTimeout=1000&socketTimeout=3000&autoReconnect=true&useSSL=false&serverTimezone=Asia/Shanghai
# 数据库用户名
db.user.0=root
# 数据库密码
db.password.0=123456

2.7 Docker 启动 Nacos

bash
docker run -d \
  # 容器名称
  --name nacos \
  # 映射控制台和 HTTP/OpenAPI 端口
  -p 8848:8848 \
  # 映射客户端 gRPC 端口
  -p 9848:9848 \
  # 指定单机模式
  -e MODE=standalone \
  # 开启鉴权能力
  -e NACOS_AUTH_ENABLE=true \
  nacos/nacos-server:v2.3.2

2.8 启动失败常见原因

  • JDK 版本不匹配
  • 端口被占用
  • MySQL 连接失败
  • 集群配置文件错误
  • 内存参数过小

2.9 学习阶段建议掌握的启动方式

从入门到进阶,建议按这个顺序练习:

  1. 单机模式启动
  2. 接入 MySQL 持久化
  3. Docker 启动
  4. 三节点集群部署
  5. 开启鉴权和反向代理

三、Nacos 作为注册中心

3.1 服务注册中心的作用

注册中心的本质是维护一张服务实例地址表。

  • 服务启动时注册自己
  • 服务关闭时注销自己
  • 调用方动态订阅服务列表
  • 结合负载均衡组件完成服务调用

3.2 注册中心工作流程

  1. 服务提供者启动
  2. 向 Nacos 注册实例
  3. Nacos 保存服务实例列表
  4. 消费者订阅服务
  5. 消费者拿到实例列表并发起调用
  6. Nacos 通过心跳或健康检查维护实例状态

3.3 临时实例和持久化实例

3.3.1 临时实例

  • 默认类型
  • 通过心跳保持存活
  • 心跳超时后会被自动剔除

3.3.2 持久化实例

  • 适合非 Spring Cloud 生态或特殊场景
  • 不依赖客户端心跳自动摘除
  • 需要服务端主动管理

重点:面试里经常会问 临时实例持久化实例 的区别,这一块一定要会。

3.4 健康检查机制

  • 临时实例:客户端主动发送心跳
  • 持久实例:服务端主动探测
  • 异常实例不会立即被删除,但可能不会被路由

3.5 权重、集群与元数据

3.5.1 权重

  • 权重越高,流量分配概率越高
  • 可用于灰度发布和流量倾斜

3.5.2 集群

  • 可按机房、区域划分
  • 优先访问同集群实例,减少跨网络调用

3.5.3 元数据

  • 可存放版本号、环境标识、灰度标签等信息

3.6 Spring Cloud Alibaba 注册中心整合

3.6.1 引入依赖

xml
<dependency>
  <groupId>com.alibaba.cloud</groupId>
  <!-- Nacos 注册中心依赖 -->
  <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>

3.6.2 服务提供者配置

yaml
server:
  # 当前服务启动端口
  port: 8001

spring:
  application:
    # 注册到 Nacos 的服务名
    name: user-service
  cloud:
    nacos:
      # Nacos 服务端地址
      server-addr: 127.0.0.1:8848
      discovery:
        # 注册中心命名空间,用于环境隔离
        namespace: dev-namespace-id
        # 服务所属分组
        group: DEFAULT_GROUP
        # 实例所属集群,可用于同机房优先路由
        cluster-name: HZ
        # true 表示临时实例,依赖心跳保活
        ephemeral: true
        metadata:
          # 自定义元数据,可用于灰度、版本标记
          version: v1
          gray: false

3.6.3 启动类

java
@SpringBootApplication
public class UserServiceApplication {
    public static void main(String[] args) {
        // 启动当前 Spring Boot 服务并注册到 Nacos
        SpringApplication.run(UserServiceApplication.class, args);
    }
}

3.6.4 控制器示例

java
@RestController
@RequestMapping("/user")
public class UserController {

    @GetMapping("/info")
    public Map<String, Object> info() {
        Map<String, Object> result = new HashMap<>();
        // 返回当前实例信息,便于观察服务调用是否命中本实例
        result.put("service", "user-service");
        result.put("port", 8001);
        result.put("time", LocalDateTime.now().toString());
        return result;
    }
}

3.7 服务消费者调用示例

3.7.1 引入依赖

xml
<dependency>
  <groupId>com.alibaba.cloud</groupId>
  <!-- 让消费者也能从 Nacos 发现服务 -->
  <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
<dependency>
  <groupId>org.springframework.cloud</groupId>
  <!-- 基于服务名做客户端负载均衡 -->
  <artifactId>spring-cloud-starter-loadbalancer</artifactId>
</dependency>

3.7.2 配置文件

yaml
server:
  port: 9001

spring:
  application:
    # 当前消费者服务名
    name: order-service
  cloud:
    nacos:
      # 指向 Nacos 注册中心地址
      server-addr: 127.0.0.1:8848

3.7.3 使用 RestTemplate + LoadBalancer

java
@Configuration
public class RestTemplateConfig {

    @Bean
    // 开启基于服务名的负载均衡调用能力
    @LoadBalanced
    public RestTemplate restTemplate() {
        return new RestTemplate();
    }
}
java
@RestController
@RequestMapping("/order")
public class OrderController {

    @Resource
    private RestTemplate restTemplate;

    @GetMapping("/create")
    public String createOrder() {
        // 这里直接写服务名,不写具体 IP:Port
        return restTemplate.getForObject("http://user-service/user/info", String.class);
    }
}

3.8 使用 OpenFeign 调用服务

3.8.1 引入依赖

xml
<dependency>
  <groupId>org.springframework.cloud</groupId>
  <!-- 基于声明式接口调用远程服务 -->
  <artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>

3.8.2 Feign 接口

java
// name 对应 Nacos 中注册的服务名
@FeignClient(name = "user-service")
public interface UserFeignClient {

    @GetMapping("/user/info")
    String getUserInfo();
}

3.8.3 启用 Feign

java
@EnableFeignClients
@SpringBootApplication
public class OrderServiceApplication {
    public static void main(String[] args) {
        // 启动服务,并启用 Feign 客户端扫描
        SpringApplication.run(OrderServiceApplication.class, args);
    }
}

3.9 手动注册实例示例

java
public class NacosNamingDemo {
    public static void main(String[] args) throws Exception {
        Properties properties = new Properties();
        // 指定 Nacos 服务端地址
        properties.put("serverAddr", "127.0.0.1:8848");

        NamingService namingService = NacosFactory.createNamingService(properties);
        // 手动注册一个服务实例
        namingService.registerInstance("pay-service", "127.0.0.1", 8080);

        // 查询指定服务下的全部实例
        List<Instance> instances = namingService.getAllInstances("pay-service");
        System.out.println(instances);
    }
}

3.10 服务注册中心学习重点

入门到进阶建议重点掌握:

  1. 服务注册与发现流程
  2. 临时实例和持久化实例
  3. 权重、集群、元数据
  4. OpenFeign 和 LoadBalancer 整合
  5. 注册中心的环境隔离设计

四、Nacos 作为配置中心

4.1 为什么需要配置中心

  • 配置统一管理
  • 配置动态更新
  • 多环境隔离
  • 敏感配置集中控制

重点:配置中心真正的价值不是“把配置放到远程”,而是“统一治理、动态生效、环境隔离”。

4.2 配置中心三大核心概念

4.2.1 Data ID

  • 一份具体配置的唯一 ID
  • 例如:order-service.yaml

4.2.2 Group

  • 配置分组
  • 例如:DEV_GROUPPROD_GROUP

4.2.3 Namespace

  • 环境隔离维度
  • 开发、测试、生产一般使用不同命名空间

4.3 Namespace、Group、Data ID 的组合关系

可以把一份配置唯一定位为:

text
Namespace + Group + Data ID

例如:

  • Namespace = dev
  • Group = ORDER_GROUP
  • Data ID = order-service.yaml

只有三者都对上,应用才能读到目标配置。

重点:读取不到配置,优先排查 NamespaceGroupData ID 这三个维度。

4.4 Nacos 配置加载规则

常见默认规则:

text
${spring.application.name}.${file-extension}

例如:

text
order-service.yaml

如果结合多环境,常见命名方式还包括:

text
${spring.application.name}-${spring.profiles.active}.${file-extension}

例如:

text
order-service-dev.yaml
order-service-test.yaml
order-service-prod.yaml

4.5 支持的配置格式

Nacos 常见支持的配置格式:

  • properties
  • yaml
  • yml
  • json
  • xml
  • text

实际项目里推荐优先使用 yaml,可读性更好。

4.6 Spring Boot 整合配置中心

4.6.1 引入依赖

xml
<dependency>
  <groupId>com.alibaba.cloud</groupId>
  <!-- Nacos 配置中心依赖 -->
  <artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
</dependency>

4.6.2 基础配置

yaml
server:
  port: 9001

spring:
  application:
    name: order-service
  config:
    import:
      # 从 Nacos 拉取 order-service.yaml 配置,并开启动态刷新
      - optional:nacos:order-service.yaml?group=DEFAULT_GROUP&refreshEnabled=true
  cloud:
    nacos:
      server-addr: 127.0.0.1:8848
      # 控制台登录用户名
      username: nacos
      # 控制台登录密码
      password: nacos

4.6.3 同时指定配置中心命名空间和分组

yaml
spring:
  application:
    name: order-service
  config:
    import:
      # 指定拉取 ORDER_GROUP 分组下的开发环境配置
      - optional:nacos:order-service-dev.yaml?group=ORDER_GROUP&refreshEnabled=true
  cloud:
    nacos:
      server-addr: 127.0.0.1:8848
      config:
        # 配置中心命名空间,与 discovery.namespace 含义不同
        namespace: dev-namespace-id
        # 配置中心默认分组
        group: ORDER_GROUP

注意:

  • spring.cloud.nacos.discovery.namespace 是给注册中心用的
  • spring.cloud.nacos.config.namespace 是给配置中心用的
  • 两者可以一样,也可以不一样

4.7 读取配置示例

java
// 让该 Bean 在配置变更后支持动态刷新
@RefreshScope
@RestController
@RequestMapping("/config")
public class ConfigController {

    // 读取超时时间,30 为默认值
    @Value("${order.timeout:30}")
    private Integer timeout;

    // 读取支付渠道,wechat 为默认值
    @Value("${order.pay-channel:wechat}")
    private String payChannel;

    @GetMapping("/get")
    public Map<String, Object> getConfig() {
        Map<String, Object> result = new HashMap<>();
        result.put("timeout", timeout);
        result.put("payChannel", payChannel);
        return result;
    }
}

4.8 动态刷新原理

  • 应用监听 Nacos 配置变更
  • 配置中心推送最新配置
  • 加了 @RefreshScope 的 Bean 会重新装配
  • 无需重启服务即可生效

重点:不是所有 Bean 都会自动刷新,通常需要 @RefreshScope 或者重新绑定配置属性。

4.9 共享配置和扩展配置

yaml
spring:
  application:
    name: order-service
  config:
    import:
      # 公共基础配置
      - optional:nacos:common.yaml?group=COMMON_GROUP&refreshEnabled=true
      # 公共数据库配置
      - optional:nacos:db.yaml?group=COMMON_GROUP&refreshEnabled=true
      # 当前服务自己的业务配置
      - optional:nacos:order-service.yaml?group=DEFAULT_GROUP&refreshEnabled=true

使用建议:

  • 公共配置放 common.yaml
  • 数据库配置放 db.yaml
  • 业务个性化配置放应用自己的 Data ID

4.10 共享配置的推荐拆分方式

典型拆分方式如下:

  • common.yaml:日志、通用开关、通用线程池配置
  • datasource.yaml:数据库连接池、MyBatis、JPA 配置
  • redis.yaml:Redis 地址、连接池、超时配置
  • mq.yaml:消息队列地址、Topic、消费者配置
  • ${spring.application.name}.yaml:应用专属配置
  • ${spring.application.name}-${spring.profiles.active}.yaml:应用专属环境配置

4.11 共享配置加载顺序与覆盖规则

spring.config.import 中,通常遵循“后导入覆盖先导入”的理解方式。

例如:

yaml
spring:
  config:
    import:
      # 默认配置,优先级相对低
      - optional:nacos:common.yaml?group=COMMON_GROUP&refreshEnabled=true
      # 对缓存相关配置做二次覆盖
      - optional:nacos:redis.yaml?group=COMMON_GROUP&refreshEnabled=true
      # 当前服务最终覆盖配置
      - optional:nacos:order-service.yaml?group=DEFAULT_GROUP&refreshEnabled=true

可以理解为:

  • common.yaml 提供默认配置
  • redis.yaml 覆盖缓存相关公共配置
  • order-service.yaml 最终覆盖当前服务自己的个性化配置

实际项目中建议:

  • 公共配置放前面
  • 业务专属配置放后面
  • 环境专属配置放最后

重点:可以把共享配置理解为“默认值”,把应用专属配置理解为“最终覆盖值”。

4.12 多环境配置示例

yaml
spring:
  application:
    name: order-service
  profiles:
    # 指定当前激活环境
    active: dev
  config:
    import:
      # 根据激活环境动态拼接 Data ID
      - optional:nacos:order-service-${spring.profiles.active}.yaml?group=DEFAULT_GROUP&refreshEnabled=true

4.13 环境隔离落地方案

推荐一套通用方案:

4.13.1 Namespace 按环境划分

  • 开发环境:dev
  • 测试环境:test
  • 预发环境:pre
  • 生产环境:prod

4.13.2 Group 按业务或项目划分

  • DEFAULT_GROUP
  • MALL_GROUP
  • PAY_GROUP
  • USER_GROUP

4.13.3 Data ID 按配置职责划分

  • common.yaml
  • datasource.yaml
  • redis.yaml
  • mall-order-service.yaml
  • mall-order-service-dev.yaml

4.13.4 一套完整映射示例

环境NamespaceGroupData ID
开发devMALL_GROUPcommon.yaml
开发devMALL_GROUPmall-order-service-dev.yaml
测试testMALL_GROUPcommon.yaml
生产prodMALL_GROUPmall-order-service-prod.yaml

4.14 注册中心和配置中心是否要共用 Namespace

两种方式都可以,但推荐有边界地使用:

4.14.1 小型项目

  • 注册中心和配置中心可以共用一个 Namespace
  • 管理成本较低

4.14.2 中大型项目

  • 可以按环境共用 Namespace
  • 但通过不同 Group 区分不同业务系统
  • 如果安全隔离要求高,也可以拆成不同命名空间

4.15 配置优先级

通常从高到低可理解为:

  1. 本地命令行参数
  2. 本地系统环境变量
  3. 本地配置文件
  4. Nacos 远程配置

实际项目中要结合 Spring Boot 版本和 spring.config.import 机制验证。

4.16 常见配置设计模板

如果要做一套相对规范的企业级配置设计,可以参考:

text
Namespace:按环境划分
Group:按系统或业务线划分
Data ID:按配置职责和服务名划分

例如:

text
dev / MALL_GROUP / common.yaml
dev / MALL_GROUP / datasource.yaml
dev / MALL_GROUP / redis.yaml
dev / MALL_GROUP / mall-order-service-dev.yaml
prod / MALL_GROUP / mall-order-service-prod.yaml

4.17 配置历史版本与回滚

配置中心在生产环境里除了“能改”,更重要的是“能回滚”。

建议重点关注:

  • 每次配置变更要记录操作人和时间
  • 关键配置发布前先在测试环境验证
  • 高风险配置要保留历史版本
  • 配置误发布后优先回滚,再排查动态刷新影响

4.18 本地缓存与容灾

Nacos 客户端通常会有本地缓存能力。

这意味着:

  • 当 Nacos 短时不可用时,应用不一定立刻完全不可用
  • 客户端可能会继续使用最近一次拉取到的配置或服务列表
  • 但这不代表可以忽略 Nacos 的高可用建设

重点:本地缓存能提升可用性,但不能替代正式的集群和容灾方案。

4.19 bootstrap.ymlspring.config.import 的区别

在较新的 Spring Boot / Spring Cloud Alibaba 项目中,更推荐使用:

  • spring.config.import

老项目常见写法:

  • bootstrap.yml

建议:

  • 新项目优先使用 spring.config.import
  • 老项目如果已经使用 bootstrap.yml,可以保持一致,但要注意版本兼容

4.20 监听配置变化示例

java
public class NacosConfigListenerDemo {
    public static void main(String[] args) throws Exception {
        Properties properties = new Properties();
        properties.put("serverAddr", "127.0.0.1:8848");

        ConfigService configService = NacosFactory.createConfigService(properties);
        // 监听 app-config.yaml 在 DEFAULT_GROUP 下的配置变化
        configService.addListener("app-config.yaml", "DEFAULT_GROUP", new Listener() {
            @Override
            public Executor getExecutor() {
                // 返回 null 表示使用默认线程池处理回调
                return null;
            }

            @Override
            public void receiveConfigInfo(String configInfo) {
                // 收到最新配置后的回调逻辑
                System.out.println("接收到最新配置:");
                System.out.println(configInfo);
            }
        });
    }
}

五、SpringBoot 和 Spring Cloud Alibaba 整合

5.1 常见依赖组合

xml
<dependencyManagement>
  <dependencies>
    <dependency>
      <groupId>com.alibaba.cloud</groupId>
      <!-- 统一管理 Spring Cloud Alibaba 相关依赖版本 -->
      <artifactId>spring-cloud-alibaba-dependencies</artifactId>
      <version>2023.0.1.0</version>
      <type>pom</type>
      <scope>import</scope>
    </dependency>
  </dependencies>
</dependencyManagement>
xml
<dependencies>
  <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>
  <dependency>
    <groupId>org.springframework.cloud</groupId>
    <!-- 声明式服务调用 -->
    <artifactId>spring-cloud-starter-openfeign</artifactId>
  </dependency>
</dependencies>

5.2 一个完整的微服务配置示例

yaml
server:
  # 当前服务端口
  port: 8088

spring:
  application:
    # 服务注册名
    name: mall-order-service
  profiles:
    # 激活 dev 环境
    active: dev
  config:
    import:
      # 导入共享配置
      - optional:nacos:common.yaml?group=COMMON_GROUP&refreshEnabled=true
      # 导入当前服务的环境专属配置
      - optional:nacos:${spring.application.name}-${spring.profiles.active}.yaml?group=DEFAULT_GROUP&refreshEnabled=true
  cloud:
    nacos:
      # Nacos 地址
      server-addr: 127.0.0.1:8848
      username: nacos
      password: nacos
      config:
        # 配置中心环境隔离
        namespace: dev-namespace-id
        group: MALL_GROUP
      discovery:
        # 注册中心环境隔离
        namespace: dev-namespace-id
        group: MALL_GROUP
        # 集群名称,便于就近访问
        cluster-name: HZ
        metadata:
          # 元数据可用于版本治理或灰度标记
          version: v1
          zone: hz-a

5.3 推荐的配置中心设计案例

mall-order-service 为例,推荐的 Nacos 配置拆分如下:

配置文件作用是否共享
common.yaml通用基础配置
datasource.yaml数据库配置
redis.yamlRedis 配置
feign.yamlFeign、超时、重试配置
mall-order-service.yaml订单服务通用配置
mall-order-service-dev.yaml订单服务开发环境配置
mall-order-service-prod.yaml订单服务生产环境配置

重点:共享配置解决复用,服务专属配置解决差异,环境配置解决隔离。

5.4 获取当前实例信息

java
@RestController
@RequestMapping("/instance")
public class InstanceController {

    @Resource
    private DiscoveryClient discoveryClient;

    @GetMapping("/current")
    public Object current() {
        // 查询当前服务名对应的实例列表
        return discoveryClient.getInstances("mall-order-service");
    }
}

5.5 通过 NacosClient 获取服务列表

java
@RestController
@RequestMapping("/nacos")
public class NacosServiceController {

    @Resource
    private NamingService namingService;

    @GetMapping("/services")
    public ListView<String> services() throws NacosException {
        // 分页查询注册中心中的服务列表
        return namingService.getServicesOfServer(1, 20);
    }
}

5.6 配置类写法示例

java
@Configuration
public class NacosClientConfig {

    @Bean
    public NamingService namingService() throws Exception {
        Properties properties = new Properties();
        // Nacos 连接信息
        properties.put("serverAddr", "127.0.0.1:8848");
        properties.put("username", "nacos");
        properties.put("password", "nacos");
        return NacosFactory.createNamingService(properties);
    }
}

5.7 配置属性绑定示例

相比大量使用 @Value,更推荐复杂配置使用 @ConfigurationProperties

java
@Data
@Component
@RefreshScope
// 将 order 前缀下的配置自动绑定到当前对象
@ConfigurationProperties(prefix = "order")
public class OrderProperties {
    private Integer timeout;
    private String payChannel;
    private Boolean enableAutoCancel;
}
java
@RestController
@RequestMapping("/order-config")
public class OrderConfigController {

    @Resource
    private OrderProperties orderProperties;

    @GetMapping
    public OrderProperties getOrderProperties() {
        // 直接返回当前绑定后的配置对象
        return orderProperties;
    }
}

重点:简单配置可以用 @Value,复杂配置更推荐 @ConfigurationProperties

5.8 与 Gateway、Sentinel、Seata 等组件协同

  • Nacos + Gateway:路由配置和服务发现
  • Nacos + Sentinel:规则配置动态推送
  • Nacos + Seata:事务组和注册中心配置
  • Nacos + Dubbo:服务注册与发现

5.9 典型项目结构建议

text
mall-parent
├─ mall-common
├─ mall-gateway
├─ mall-user-service
├─ mall-order-service
├─ mall-product-service
└─ mall-api

Nacos 中的配置建议拆分为:

  • common.yaml
  • datasource.yaml
  • redis.yaml
  • mall-order-service-dev.yaml
  • mall-user-service-dev.yaml

六、Nacos 核心机制与高级特性

6.1 服务心跳机制

  • 临时实例默认依赖客户端定时上报心跳
  • 一旦长时间未收到心跳,实例会被标记不健康
  • 超过阈值后实例会被移除

6.2 服务订阅与推送

  • 客户端可以订阅服务变化
  • Nacos 服务端会推送变更
  • 客户端本地会缓存服务列表

6.3 注册中心与配置中心的通信特点

从理解原理的角度,可以这样记:

  • 注册中心更关注实例变化和健康状态
  • 配置中心更关注配置变更和动态推送
  • 客户端通常会维护本地缓存,提高访问效率和容错能力

6.4 AP 与 CP 模式

Nacos 在不同场景下支持不同一致性策略。

6.4.1 AP 模式

  • 偏向高可用
  • 适合临时实例注册发现
  • 允许短暂数据不一致

6.4.2 CP 模式

  • 偏向强一致
  • 适合持久实例和重要数据场景
  • 对一致性要求更高

重点:AP / CP 是 Nacos 的高频面试考点。

6.5 服务元数据

示例:

yaml
spring:
  cloud:
    nacos:
      discovery:
        metadata:
          # 服务版本
          version: v2
          # 是否灰度实例
          gray: true
          # 区域标识
          region: east

使用场景:

  • 灰度发布
  • 地域路由
  • 版本隔离

6.5 权重路由

可以在 Nacos 控制台给某个实例设置不同权重。

  • 正常实例权重设置为 1
  • 灰度实例权重设置为 0.2
  • 权重设置为 0 时一般不会分配流量

6.6 灰度发布思路

Nacos 本身不是完整的灰度平台,但它提供了灰度治理的重要基础能力:

  • 通过权重控制流量比例
  • 通过元数据标记灰度实例
  • 通过集群或分组实现流量隔离
  • 结合 Gateway / Sentinel 实现更细粒度灰度

6.7 命名空间隔离

环境隔离建议:

  • 开发环境一个 Namespace
  • 测试环境一个 Namespace
  • 生产环境一个 Namespace

不要把多环境配置放在同一个命名空间混用。

6.8 分组设计

分组适合做业务维度划分:

  • DEFAULT_GROUP
  • ORDER_GROUP
  • USER_GROUP
  • PAY_GROUP

6.9 配置加密

敏感信息不要明文暴露。

  • 数据库密码
  • Redis 密码
  • AccessKey / SecretKey

常见做法:

  • 结合 KMS 或密钥管理系统
  • 在应用层做解密
  • 使用外部密文管理方案

6.10 鉴权配置

conf/application.properties

properties
# 开启 Nacos 鉴权
nacos.core.auth.enabled=true
# 服务端身份标识 key
nacos.core.auth.server.identity.key=serverIdentity
# 服务端身份标识 value
nacos.core.auth.server.identity.value=security
# Token 加密密钥,生产环境务必修改
nacos.core.auth.plugin.nacos.token.secret.key=ThisIsASecretKeyForNacosAuthPluginPleaseChangeIt

6.11 Java SDK 发布配置示例

java
public class PublishConfigDemo {
    public static void main(String[] args) throws Exception {
        Properties properties = new Properties();
        properties.put("serverAddr", "127.0.0.1:8848");
        ConfigService configService = NacosFactory.createConfigService(properties);

        // 发布 pay-service.yaml 配置到 DEFAULT_GROUP 分组
        boolean success = configService.publishConfig(
                "pay-service.yaml",
                "DEFAULT_GROUP",
                "pay.timeout=60\npay.notify-url=https://api.example.com/callback"
        );

        System.out.println("发布结果: " + success);
    }
}

6.12 高阶能力学习重点

进阶到精通阶段,建议重点攻克这些内容:

  1. AP / CP 模式
  2. 权重、集群、元数据
  3. 灰度发布思路
  4. 鉴权与安全
  5. 集群部署与容灾

七、Nacos 集群与生产部署

7.1 为什么生产环境要集群

  • 避免单点故障
  • 提高可用性
  • 支撑更多服务实例和配置请求

7.2 官方推荐的生产部署思路

  • 3 台及以上 Nacos 节点
  • 1 个 MySQL 主库或高可用数据库
  • 前置 Nginx / SLB / LVS

7.3 集群部署步骤

7.3.1 配置数据库

确保所有 Nacos 节点连接同一个数据库。

7.3.2 配置集群节点列表

conf/cluster.conf

text
192.168.10.101:8848
192.168.10.102:8848
192.168.10.103:8848

7.3.3 修改数据库连接

properties
# 单数据库模式
db.num=1
# 配置库连接地址
db.url.0=jdbc:mysql://192.168.10.200:3306/nacos_config?characterEncoding=utf8&connectTimeout=1000&socketTimeout=3000&autoReconnect=true&useSSL=false
# 数据库账号
db.user.0=root
# 数据库密码
db.password.0=123456

7.3.4 启动每个节点

bash
# 集群模式下逐台启动 Nacos 节点
sh startup.sh

7.4 Nginx 反向代理示例

nginx
upstream nacos-cluster {
    # Nacos 集群节点列表
    server 192.168.10.101:8848;
    server 192.168.10.102:8848;
    server 192.168.10.103:8848;
}

server {
    # 对外统一暴露的访问端口
    listen 8848;

    location / {
        # 将请求转发到 Nacos 集群
        proxy_pass http://nacos-cluster;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    }
}

7.5 JVM 参数优化

bin/startup.sh 中可按机器配置调整:

bash
# 设置 Nacos JVM 初始堆、最大堆和新生代大小
JAVA_OPT="${JAVA_OPT} -Xms1g -Xmx1g -Xmn512m"

7.6 数据库高可用建议

  • 使用主从或 MGR
  • 定期备份 Nacos 配置库
  • 重要配置变更要留痕

7.7 生产环境注意事项

  • 不要使用默认密码
  • 一定开启鉴权
  • 做好命名空间隔离
  • 对核心配置变更做审批
  • 控制台只开放给内网或 VPN

重点:生产环境里最重要的不是“能跑起来”,而是“能稳定、能回滚、能审计、能隔离”。

八、Nacos OpenAPI 与运维管理

8.1 OpenAPI 的作用

  • 自动化注册实例
  • 自动化发布配置
  • 运维平台集成
  • CI/CD 流程对接

8.2 发布配置接口示例

bash
curl -X POST "http://127.0.0.1:8848/nacos/v1/cs/configs" \
  # 配置文件唯一标识
  -d "dataId=app.yaml" \
  # 配置分组
  -d "group=DEFAULT_GROUP" \
  # 配置正文内容
  -d "content=app.name=mall"

8.3 查询配置接口示例

bash
curl -G "http://127.0.0.1:8848/nacos/v1/cs/configs" \
  --data-urlencode "dataId=app.yaml" \
  --data-urlencode "group=DEFAULT_GROUP"

8.4 注册实例接口示例

bash
curl -X POST "http://127.0.0.1:8848/nacos/v1/ns/instance" \
  # 服务名称
  -d "serviceName=pay-service" \
  # 实例 IP
  -d "ip=127.0.0.1" \
  # 实例端口
  -d "port=8080"

8.5 查询实例列表接口示例

bash
curl -G "http://127.0.0.1:8848/nacos/v1/ns/instance/list" \
  --data-urlencode "serviceName=pay-service"

8.6 删除实例接口示例

bash
curl -X DELETE "http://127.0.0.1:8848/nacos/v1/ns/instance" \
  -d "serviceName=pay-service" \
  -d "ip=127.0.0.1" \
  -d "port=8080"

8.7 运维关注指标

  • 服务数量
  • 实例数量
  • 心跳异常数
  • 配置发布次数
  • 长轮询连接数
  • CPU、内存、GC、线程数

8.8 控制台常用操作

  • 创建命名空间
  • 新增配置
  • 编辑配置
  • 发布配置
  • 查看服务列表
  • 实例上下线
  • 修改实例权重

8.9 运维侧重点

运维和平台同学通常会重点关注:

  • 配置是否可审计
  • 实例是否健康
  • 集群是否高可用
  • 是否有备份和回滚机制
  • 控制台权限是否收敛

九、常见面试题与故障排查

9.1 Nacos 是注册中心还是配置中心

二者都是。

  • 作为注册中心,负责服务注册与发现
  • 作为配置中心,负责配置统一管理和动态推送

9.2 Nacos 为什么比 Eureka 更适合 Spring Cloud Alibaba

  • 既支持注册中心又支持配置中心
  • 与阿里生态集成更紧密
  • 支持命名空间、分组、权重、元数据
  • 控制台能力更完整

9.3 Nacos 配置不生效怎么办

排查顺序:

  1. Data ID 是否写对
  2. Group 是否一致
  3. Namespace 是否一致
  4. 是否开启了 spring.config.import
  5. Bean 是否加了 @RefreshScope
  6. 配置格式是否正确
  7. 是否被后加载配置覆盖

9.4 服务注册不上去怎么办

重点排查:

  • server-addr 是否正确
  • 服务名是否为空
  • Nacos 是否启动成功
  • 网络和端口是否打通
  • 鉴权账号密码是否正确

9.5 Nacos 心跳异常怎么查

  • 检查客户端和服务端网络
  • 检查实例机器是否长时间 Full GC
  • 检查服务端负载是否过高
  • 检查时间同步是否异常

9.6 线上配置误发布怎么办

  • 先回滚配置内容
  • 确认是否触发动态刷新
  • 评估影响范围
  • 对关键配置接入审批与版本管理

9.7 如何设计多环境配置

推荐方式:

  • Namespace 负责环境隔离
  • Group 负责业务分类
  • Data ID 负责具体应用配置

9.9 Nacos 的高频面试重点

如果是面试复习,优先掌握以下内容:

  1. Nacos 是什么,核心功能有哪些
  2. 注册中心和配置中心的区别
  3. 临时实例和持久化实例
  4. Namespace、Group、Data ID 的作用
  5. AP / CP 模式
  6. 动态刷新原理
  7. 共享配置加载顺序
  8. 生产环境部署方案

9.8 Nacos 和 Apollo 怎么选

  • 只看 Spring Cloud Alibaba 微服务生态,优先 Nacos
  • 更看重配置发布流程、灰度和审计体系,可比较 Apollo
  • 既要注册中心又要配置中心,Nacos 更统一

十、Nacos 最佳实践

10.1 命名规范建议

10.1.1 服务名规范

text
mall-user-service
mall-order-service
mall-pay-service

10.1.2 Data ID 规范

text
common.yaml
datasource.yaml
mall-user-service-dev.yaml
mall-order-service-prod.yaml

10.2 环境隔离建议

  • 开发、测试、生产分不同 Namespace
  • 不同环境使用不同数据库和中间件账号

10.3 配置拆分建议

把配置按职责拆开:

  • 应用配置
  • 数据源配置
  • 缓存配置
  • 消息队列配置
  • 第三方接口配置

10.4 安全建议

  • 打开鉴权
  • 修改默认密码
  • 限制控制台访问 IP
  • 对敏感配置做脱敏或加密

10.5 发布流程建议

  1. 先在测试环境验证配置
  2. 核对命名空间和分组
  3. 小流量灰度验证
  4. 再发布生产环境

10.6 高可用建议

  • Nacos 至少 3 节点
  • MySQL 做高可用
  • 网关层做负载均衡
  • 关键配置做好备份

10.7 学习路线建议

从入门到进阶可以这样学:

  1. 先学 Nacos 单机安装与控制台使用
  2. 再学服务注册与发现
  3. 再学配置中心和动态刷新
  4. 然后整合 Spring Cloud Alibaba
  5. 最后学习集群、鉴权、OpenAPI 和生产实践

10.8 一套完整配置示例

yaml
server:
  port: 8081

spring:
  application:
    # 注册到 Nacos 的服务名
    name: mall-user-service
  profiles:
    # 当前运行环境
    active: dev
  config:
    import:
      # 共享基础配置
      - optional:nacos:common.yaml?group=COMMON_GROUP&refreshEnabled=true
      # 共享数据源配置
      - optional:nacos:datasource.yaml?group=COMMON_GROUP&refreshEnabled=true
      # 当前服务的环境专属配置
      - optional:nacos:${spring.application.name}-${spring.profiles.active}.yaml?group=DEFAULT_GROUP&refreshEnabled=true
  cloud:
    nacos:
      server-addr: 127.0.0.1:8848
      username: nacos
      password: nacos
      discovery:
        # 注册中心命名空间
        namespace: dev-namespace-id
        group: DEFAULT_GROUP
        # 同集群优先访问
        cluster-name: HZ
        metadata:
          # 服务版本号
          version: v1
          # 是否灰度实例
          gray: false

10.9 总结

Nacos 是微服务体系中非常核心的基础组件,既能做注册中心,也能做配置中心。

  • 入门阶段要先掌握控制台、命名空间、分组、Data ID
  • 进阶阶段要掌握动态配置、服务发现、OpenFeign 调用
  • 高阶阶段要掌握集群部署、鉴权、安全治理和生产最佳实践

把这套内容真正跑通之后,基本就可以覆盖大部分 Java 微服务项目里的 Nacos 使用场景。