Appearance
Nacos 学习指南
导航目录
- 一、Nacos 概述与核心能力
- 二、Nacos 环境安装与启动
- 三、Nacos 作为注册中心
- 四、Nacos 作为配置中心
- 五、SpringBoot 和 Spring Cloud Alibaba 整合
- 六、Nacos 核心机制与高级特性
- 七、Nacos 集群与生产部署
- 八、Nacos OpenAPI 与运维管理
- 九、常见面试题与故障排查
- 十、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 的区别
| 对比项 | Nacos | Eureka | Consul | Apollo |
|---|---|---|---|---|
| 注册中心 | 支持 | 支持 | 支持 | 不擅长 |
| 配置中心 | 支持 | 不支持 | 一般 | 强 |
| 服务健康检查 | 支持 | 支持 | 支持 | 不涉及 |
| DNS/HTTP 接口 | 支持 | HTTP | DNS/HTTP | HTTP |
| 控制台 | 支持 | 一般 | 支持 | 支持 |
| 与 Spring Cloud Alibaba 集成 | 非常好 | 一般 | 一般 | 一般 |
1.5 Nacos 核心概念
1.5.1 Namespace
- 用于环境隔离
- 常见划分:
dev、test、prod
1.5.2 Group
- 用于服务或配置分组
- 常见分组:
DEFAULT_GROUP、ORDER_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 | 环境隔离 | dev、test、prod | 不建议 |
| Group | 业务分类 | DEFAULT_GROUP、ORDER_GROUP | 适度 |
| Data ID | 具体配置文件标识 | order-service.yaml | 经常使用 |
可以记成一句话:
Namespace解决环境问题Group解决业务归类问题Data ID解决具体配置文件定位问题
1.7 注册中心和配置中心中的三个维度
在 Nacos 里,注册中心和配置中心都能使用 Namespace、Group,但使用侧重点不同:
- 注册中心里,
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/bin2.2.2 单机启动
Linux / Mac:
bash
# `-m standalone` 表示以单机模式启动,适合本地开发和学习
sh startup.sh -m standaloneWindows:
bash
# Windows 下同样使用 standalone 单机模式
startup.cmd -m standalone2.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.sh2.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.sql2.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=1234562.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.22.8 启动失败常见原因
- JDK 版本不匹配
- 端口被占用
- MySQL 连接失败
- 集群配置文件错误
- 内存参数过小
2.9 学习阶段建议掌握的启动方式
从入门到进阶,建议按这个顺序练习:
- 单机模式启动
- 接入 MySQL 持久化
- Docker 启动
- 三节点集群部署
- 开启鉴权和反向代理
三、Nacos 作为注册中心
3.1 服务注册中心的作用
注册中心的本质是维护一张服务实例地址表。
- 服务启动时注册自己
- 服务关闭时注销自己
- 调用方动态订阅服务列表
- 结合负载均衡组件完成服务调用
3.2 注册中心工作流程
- 服务提供者启动
- 向 Nacos 注册实例
- Nacos 保存服务实例列表
- 消费者订阅服务
- 消费者拿到实例列表并发起调用
- 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: false3.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:88483.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 服务注册中心学习重点
入门到进阶建议重点掌握:
- 服务注册与发现流程
- 临时实例和持久化实例
- 权重、集群、元数据
- OpenFeign 和 LoadBalancer 整合
- 注册中心的环境隔离设计
四、Nacos 作为配置中心
4.1 为什么需要配置中心
- 配置统一管理
- 配置动态更新
- 多环境隔离
- 敏感配置集中控制
重点:配置中心真正的价值不是“把配置放到远程”,而是“统一治理、动态生效、环境隔离”。
4.2 配置中心三大核心概念
4.2.1 Data ID
- 一份具体配置的唯一 ID
- 例如:
order-service.yaml
4.2.2 Group
- 配置分组
- 例如:
DEV_GROUP、PROD_GROUP
4.2.3 Namespace
- 环境隔离维度
- 开发、测试、生产一般使用不同命名空间
4.3 Namespace、Group、Data ID 的组合关系
可以把一份配置唯一定位为:
text
Namespace + Group + Data ID例如:
Namespace = devGroup = ORDER_GROUPData ID = order-service.yaml
只有三者都对上,应用才能读到目标配置。
重点:读取不到配置,优先排查 Namespace、Group、Data 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.yaml4.5 支持的配置格式
Nacos 常见支持的配置格式:
propertiesyamlymljsonxmltext
实际项目里推荐优先使用 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: nacos4.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=true4.13 环境隔离落地方案
推荐一套通用方案:
4.13.1 Namespace 按环境划分
- 开发环境:
dev - 测试环境:
test - 预发环境:
pre - 生产环境:
prod
4.13.2 Group 按业务或项目划分
DEFAULT_GROUPMALL_GROUPPAY_GROUPUSER_GROUP
4.13.3 Data ID 按配置职责划分
common.yamldatasource.yamlredis.yamlmall-order-service.yamlmall-order-service-dev.yaml
4.13.4 一套完整映射示例
| 环境 | Namespace | Group | Data ID |
|---|---|---|---|
| 开发 | dev | MALL_GROUP | common.yaml |
| 开发 | dev | MALL_GROUP | mall-order-service-dev.yaml |
| 测试 | test | MALL_GROUP | common.yaml |
| 生产 | prod | MALL_GROUP | mall-order-service-prod.yaml |
4.14 注册中心和配置中心是否要共用 Namespace
两种方式都可以,但推荐有边界地使用:
4.14.1 小型项目
- 注册中心和配置中心可以共用一个
Namespace - 管理成本较低
4.14.2 中大型项目
- 可以按环境共用
Namespace - 但通过不同
Group区分不同业务系统 - 如果安全隔离要求高,也可以拆成不同命名空间
4.15 配置优先级
通常从高到低可理解为:
- 本地命令行参数
- 本地系统环境变量
- 本地配置文件
- 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.yaml4.17 配置历史版本与回滚
配置中心在生产环境里除了“能改”,更重要的是“能回滚”。
建议重点关注:
- 每次配置变更要记录操作人和时间
- 关键配置发布前先在测试环境验证
- 高风险配置要保留历史版本
- 配置误发布后优先回滚,再排查动态刷新影响
4.18 本地缓存与容灾
Nacos 客户端通常会有本地缓存能力。
这意味着:
- 当 Nacos 短时不可用时,应用不一定立刻完全不可用
- 客户端可能会继续使用最近一次拉取到的配置或服务列表
- 但这不代表可以忽略 Nacos 的高可用建设
重点:本地缓存能提升可用性,但不能替代正式的集群和容灾方案。
4.19 bootstrap.yml 和 spring.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-a5.3 推荐的配置中心设计案例
以 mall-order-service 为例,推荐的 Nacos 配置拆分如下:
| 配置文件 | 作用 | 是否共享 |
|---|---|---|
common.yaml | 通用基础配置 | 是 |
datasource.yaml | 数据库配置 | 是 |
redis.yaml | Redis 配置 | 是 |
feign.yaml | Feign、超时、重试配置 | 是 |
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-apiNacos 中的配置建议拆分为:
common.yamldatasource.yamlredis.yamlmall-order-service-dev.yamlmall-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_GROUPORDER_GROUPUSER_GROUPPAY_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=ThisIsASecretKeyForNacosAuthPluginPleaseChangeIt6.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 高阶能力学习重点
进阶到精通阶段,建议重点攻克这些内容:
- AP / CP 模式
- 权重、集群、元数据
- 灰度发布思路
- 鉴权与安全
- 集群部署与容灾
七、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:88487.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=1234567.3.4 启动每个节点
bash
# 集群模式下逐台启动 Nacos 节点
sh startup.sh7.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 配置不生效怎么办
排查顺序:
Data ID是否写对Group是否一致Namespace是否一致- 是否开启了
spring.config.import - Bean 是否加了
@RefreshScope - 配置格式是否正确
- 是否被后加载配置覆盖
9.4 服务注册不上去怎么办
重点排查:
server-addr是否正确- 服务名是否为空
- Nacos 是否启动成功
- 网络和端口是否打通
- 鉴权账号密码是否正确
9.5 Nacos 心跳异常怎么查
- 检查客户端和服务端网络
- 检查实例机器是否长时间 Full GC
- 检查服务端负载是否过高
- 检查时间同步是否异常
9.6 线上配置误发布怎么办
- 先回滚配置内容
- 确认是否触发动态刷新
- 评估影响范围
- 对关键配置接入审批与版本管理
9.7 如何设计多环境配置
推荐方式:
Namespace负责环境隔离Group负责业务分类Data ID负责具体应用配置
9.9 Nacos 的高频面试重点
如果是面试复习,优先掌握以下内容:
- Nacos 是什么,核心功能有哪些
- 注册中心和配置中心的区别
- 临时实例和持久化实例
- Namespace、Group、Data ID 的作用
- AP / CP 模式
- 动态刷新原理
- 共享配置加载顺序
- 生产环境部署方案
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-service10.1.2 Data ID 规范
text
common.yaml
datasource.yaml
mall-user-service-dev.yaml
mall-order-service-prod.yaml10.2 环境隔离建议
- 开发、测试、生产分不同 Namespace
- 不同环境使用不同数据库和中间件账号
10.3 配置拆分建议
把配置按职责拆开:
- 应用配置
- 数据源配置
- 缓存配置
- 消息队列配置
- 第三方接口配置
10.4 安全建议
- 打开鉴权
- 修改默认密码
- 限制控制台访问 IP
- 对敏感配置做脱敏或加密
10.5 发布流程建议
- 先在测试环境验证配置
- 核对命名空间和分组
- 小流量灰度验证
- 再发布生产环境
10.6 高可用建议
- Nacos 至少 3 节点
- MySQL 做高可用
- 网关层做负载均衡
- 关键配置做好备份
10.7 学习路线建议
从入门到进阶可以这样学:
- 先学 Nacos 单机安装与控制台使用
- 再学服务注册与发现
- 再学配置中心和动态刷新
- 然后整合 Spring Cloud Alibaba
- 最后学习集群、鉴权、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: false10.9 总结
Nacos 是微服务体系中非常核心的基础组件,既能做注册中心,也能做配置中心。
- 入门阶段要先掌握控制台、命名空间、分组、Data ID
- 进阶阶段要掌握动态配置、服务发现、OpenFeign 调用
- 高阶阶段要掌握集群部署、鉴权、安全治理和生产最佳实践
把这套内容真正跑通之后,基本就可以覆盖大部分 Java 微服务项目里的 Nacos 使用场景。