Nacos

技术栈
工具链
微服务服务发现配置管理注册中心动态配置阿里云

概览

Nacos

Nacos(Dynamic Naming and Configuration Service)是阿里巴巴开源的动态服务发现、配置管理和服务管理平台,是 Spring Cloud Alibaba 的核心组件之一。

是什么

Nacos = Naming(注册中心) + Configuration(配置中心) + Service(服务管理)。它帮助微服务架构实现服务自动注册与发现、动态配置下发、健康检查、流量管理等。

解决什么问题

  • 服务注册与发现:替代 Eureka/ZooKeeper/Consul,支持 AP/CP 模式切换
  • 动态配置管理:替代 Spring Cloud Config/Apollo,支持配置热更新
  • DNS 服务:支持 DNS-Based 服务发现
  • 健康检查:TCP/HTTP/MySQL 等多种检查方式
  • 灰度发布:支持流量染色、蓝绿部署

关键特性

  • AP/CP 双模式:通过 nacos.core.protocol.raft.strictMode 切换
  • 配置热更新@RefreshScope + @NacosValue 实时生效
  • 多环境隔离:Namespace(环境)→ Group(分组)→ Data ID(配置)
  • 权限控制:1.2+ 内置 RBAC
  • 控制台 UI:开箱即用的可视化管控界面
  • 生态集成:Spring Cloud、Dubbo、gRPC、K8s

安装

Nacos 安装与初始化

1. 环境准备

要求 说明
操作系统 Linux / macOS / Windows(推荐 Linux 生产部署)
JDK JDK 8+(推荐 JDK 11),需要 JAVA_HOME 环境变量
Maven 3.2.x+(源码编译时需要)
MySQL 5.6.5+(生产模式持久化配置需要,开发模式用内嵌 Derby)
端口 默认 8848(主端口)、9848(gRPC 客户端)、9849(gRPC Server)

2. 安装命令

方式一:二进制包(推荐)

# 下载最新稳定版
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

# Linux/Unix 启动(单机模式)
sh startup.sh -m standalone

# Windows
startup.cmd -m standalone

方式二:Docker 部署

docker run --name nacos -d \
  -e MODE=standalone \
  -e PREFER_HOST_MODE=hostname \
  -p 8848:8848 \
  -p 9848:9848 \
  nacos/nacos-server:v2.3.2

方式三:Kubernetes 部署

# 使用 Helm
helm repo add nacos https://nacos.io/helm-charts
helm install nacos nacos/nacos \
  --set mode=standalone \
  --set service.type=NodePort

验证启动

# 访问控制台
curl http://localhost:8848/nacos
# 浏览器打开 http://localhost:8848/nacos
# 默认账号密码: nacos/nacos

生产模式(MySQL 持久化)

  1. 创建数据库并导入初始化脚本:
CREATE DATABASE nacos_config DEFAULT CHARACTER SET utf8mb4;
  1. 执行 conf/mysql-schema.sql

  2. 修改 conf/application.properties

spring.datasource.platform=mysql
db.num=1
db.url.0=jdbc:mysql://127.0.0.1:3306/nacos_config?characterEncoding=utf8&connectTimeout=1000&socketTimeout=3000&autoReconnect=true
db.user=root
db.password=your_password

3. 常见安装问题

问题 解决方案
端口被占用 `netstat -tlnp
启动内存不足 修改 bin/startup.sh-Xms -Xmx -Xmn 参数,缩减 JVM 堆大小
Docker 无法访问宿主机 设置 -e PREFER_HOST_MODE=hostname 并用 --network host
MySQL 8.0 连接失败 MySQL 8.0 默认加密方式变更,需 ALTER USER 'root'@'%' IDENTIFIED WITH mysql_native_password BY 'password';
集群模式启动慢 检查 cluster.conf 中 IP 列表是否正确,确保节点间 7848 端口互通
忘记密码(1.x) sh startup.sh -m standalone -Dnacos.standalone.auth.enabled=true 后通过 API 重置
控制台访问 404 确认访问路径为 /nacos 而非 /,完整 URL: http://host:8848/nacos

示例

目标

演示 Spring Boot 应用接入 Nacos,实现服务注册发现 + 动态配置热更新。启动两个实例后,通过 Nacos 控制台修改配置,应用无需重启即可生效。

完整代码

1. pom.xml 依赖

<dependency>
    <groupId>com.alibaba.cloud</groupId>
    <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
    <version>2023.0.1.0</version>
</dependency>
<dependency>
    <groupId>com.alibaba.cloud</groupId>
    <artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
    <version>2023.0.1.0</version>
</dependency>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
</dependency>

2. bootstrap.yml

spring:
  application:
    name: demo-service
  cloud:
    nacos:
      discovery:
        server-addr: 127.0.0.1:8848
        namespace: public
        group: DEFAULT_GROUP
      config:
        server-addr: 127.0.0.1:8848
        namespace: public
        group: DEFAULT_GROUP
        file-extension: yaml
        refresh-enabled: true

3. 动态配置类

import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.Value;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RefreshScope  // 关键:开启配置热更新
public class ConfigController {

    @Value("${app.message:Hello Nacos!}")
    private String message;

    @Value("${app.feature.enabled:false}")
    private boolean featureEnabled;

    @GetMapping("/config")
    public String getConfig() {
        return String.format("message=%s, featureEnabled=%s", message, featureEnabled);
    }
}

4. 启动类

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;

@SpringBootApplication
@EnableDiscoveryClient
public class DemoApplication {
    public static void main(String[] args) {
        SpringApplication.run(DemoApplication.class, args);
    }
}

5. Nacos 控制台配置

在 Nacos 控制台 配置管理 → 配置列表 中新建配置:

  • Data ID: demo-service.yaml
  • Group: DEFAULT_GROUP
  • 配置内容:
app:
  message: "Hello from Nacos Config!"
  feature:
    enabled: true

运行步骤

# 1. 启动 Nacos(单机)
cd nacos/bin &;& sh startup.sh -m standalone

# 2. 启动应用实例1(默认8080)
mvn spring-boot:run

# 3. 启动应用实例2(8081端口)
mvn spring-boot:run -Dspring-boot.run.arguments=--server.port=8081

# 4. 验证服务注册
curl http://localhost:8848/nacos/v1/ns/instance/list?serviceName=demo-service

# 5. 验证配置
curl http://localhost:8080/config

# 6. 在 Nacos 控制台修改 app.message,再次请求观察热更新
curl http://localhost:8080/config

预期输出

// 服务列表 - 两个健康实例
{"hosts":[{"ip":"192.168.1.5","port":8080,"healthy":true},
          {"ip":"192.168.1.5","port":8081,"healthy":true}]}

// 配置接口
message=Hello from Nacos Config!, featureEnabled=true

// 控制台修改后(无需重启)
message=New value from Nacos!, featureEnabled=true

关键点

  • @RefreshScope 实现配置热更新,无需重启应用
  • Data ID 命名规则:${spring.application.name}.${file-extension}
  • Nacos 服务列表实时反映实例上下线,支持主动健康检查
  • 可结合 @NacosValue 注解实现更细粒度的配置注入

教程

前言

在微服务架构中,服务实例的 IP/端口是动态变化的,如果每个服务都硬编码调用地址,系统将寸步难行。Nacos 作为阿里开源的注册 + 配置中心,解决了"服务在哪"和"配置怎么管"两个核心问题。


第一章:理解服务注册与发现

1.1 没有注册中心时

ServiceA 调用 ServiceB
  → 需要在代码/配置文件里写死 ServiceB 的地址
  → ServiceB 扩容、缩容、迁移 → 必须修改 ServiceA 的配置
  → 修改 → 重启 → 中断服务

1.2 有了 Nacos 后

ServiceB 启动 → 向 Nacos 注册(IP:Port)
ServiceA 启动 → 从 Nacos 订阅 ServiceB 的地址列表
ServiceB 扩容 → Nacos 推送新实例给 ServiceA
ServiceB 宕机 → Nacos 健康检查剔除,ServiceA 自动感知

1.3 Nacos 核心概念

概念 说明 类比
Namespace(命名空间) 环境隔离(dev/test/prod) Git 分支
Group(分组) 同一环境下的业务分组 文件夹
Service(服务) 一组提供相同功能的实例 一个应用
Instance(实例) 一个具体的服务节点 一台机器上的进程
Data ID(配置标识) 唯一标识一个配置 文件名
Config(配置内容) 具体的配置项 文件内容

第二章:AP 与 CP 模式的选择

2.1 CAP 回顾

  • C(Consistency):所有节点同一时刻数据一致
  • A(Availability):每个请求都能收到响应
  • P(Partition Tolerance):网络分区时系统仍能工作

CAP 不可兼得,只能三选二。

2.2 Nacos 的独特之处:AP + CP 可切换

# AP 模式(默认):优先保证可用性
nacos.core.protocol.raft.strictMode=false

# CP 模式:优先保证一致性(适合对数据一致性要求高的场景)
nacos.core.protocol.raft.strictMode=true
模式 适用场景 取舍
AP 一般微服务注册发现 网络分区时各节点可独立工作,恢复后自动合并
CP 金融/支付等强一致场景 网络分区时少数节点拒绝写入

这是 Nacos 相比 Eureka(纯 AP)和 ZooKeeper(纯 CP)的核心优势。

2.3 健康检查机制

临时实例(ephemeral=true,默认)
  → 客户端主动心跳(5s 间隔)
  → 15s 无心跳 → 标记不健康
  → 30s 无心跳 → 剔除

永久实例(ephemeral=false)
  → Nacos Server 主动探测(TCP/HTTP/MySQL)
  → 探测失败 → 标记不健康但不剔除

第三章:配置管理深入

3.1 配置的三级隔离

Namespace(环境)→ Group(业务域)→ Data ID(配置项)

示例:
  dev → ORDER_GROUP → order-service.yaml
  prod → ORDER_GROUP → order-service.yaml

3.2 配置优先级(Spring Cloud)

1. 命令行参数(最高)
2. Nacos 扩展配置(shared-configs → extension-configs)
3. Nacos 主配置(${spring.application.name}.${file-extension})
4. application.yml(本地)
5. bootstrap.yml(本地,最低)

3.3 灰度配置发布

# 在 Nacos 控制台:配置管理 → 灰度发布
# 指定 IP 白名单,仅对特定实例生效
gray-ip-list: 192.168.1.100,192.168.1.101

3.4 配置回滚

Nacos 自动保存每次发布的快照(最多 30 个版本),控制台一键回滚到任意历史版本。


第四章:Nacos 集群部署要点

4.1 推荐架构

                  ┌─────────────┐
                  │   Nginx LB  │
                  └──────┬──────┘
          ┌──────────────┼──────────────┐
    ┌─────┴─────┐  ┌─────┴─────┐  ┌─────┴─────┐
    │ Nacos #1  │  │ Nacos #2  │  │ Nacos #3  │
    └─────┬─────┘  └─────┬─────┘  └─────┬─────┘
          └──────────────┼──────────────┘
                  ┌──────┴──────┐
                  │    MySQL    │  ← 外部存储(共享)
                  └─────────────┘

4.2 关键配置

# cluster.conf(每个节点都要配置)
192.168.1.10:8848
192.168.1.11:8848
192.168.1.12:8848

三个节点形成 Raft 集群,Leader 负责写,Follower 可读。


第五章:与其他注册中心对比

特性 Nacos Eureka Consul ZooKeeper
CAP 模型 AP/CP 可切换 AP CP CP
配置中心 ✅ 内置 ✅ Key/Value ❌(需 Curator)
健康检查 TCP/HTTP/MySQL/心跳 心跳 TCP/HTTP/gRPC KeepAlive
控制台 ✅ 功能完整 ✅ 只读 ❌(需第三方)
多数据中心
Spring Cloud ✅ 原生 ✅ 原生
Dubbo 支持 ✅ 首选
雪崩保护

思考题

  1. 在 CAP 理论中,Nacos 如何做到 AP 和 CP 模式切换?底层的 Raft 协议扮演什么角色?
  2. 配置热更新时,Nacos 客户端是如何感知到配置变化的?长轮询机制的原理是什么?
  3. 如果 Nacos 集群全部宕机,已注册的服务之间还能互相调用吗?为什么?
  4. 为什么 Nacos 2.x 将 gRPC 作为默认通信协议?相比 HTTP 有什么优势?

下一步

  • 学习 Spring Cloud Gateway + Nacos 实现动态路由
  • 学习 Sentinel + Nacos 实现限流规则持久化
  • 学习 Dubbo + Nacos 实现 RPC 服务治理

参考资料

暂无参考文献