04. Nacos 面试题库(知识点精讲版)
本文档遵循「先讲清知识点,再给面试答法」的原则。每道题先解释为什么 和原理,再给出面试中可以直接使用的表达方式。
一、入门级面试题
Q1. Nacos 是什么?解决了哪些问题?
知识点:微服务基础设施的痛点
单体应用不存在这些问题------配置写在本地文件,服务地址直接调用。但拆成微服务后,两个核心问题出现了:
配置管理痛点:
| 痛点 | 具体表现 |
|---|---|
| 配置分散 | 10 个服务有 10 份配置,改一个公共参数要逐个改 |
| 改配置要重启 | 修改限流阈值、数据库连接数都要重新发布 |
| 多环境混乱 | dev/test/prod 配置容易搞混,生产事故的常见根因 |
| 无审计追踪 | 谁在何时改了什么,无从查起 |
服务发现痛点:
| 痛点 | 具体表现 |
|---|---|
| 地址写死 | IP 变了所有调用方都要改 |
| 扩容不感知 | 新增实例调用方不知道,流量打不过去 |
| 故障不摘除 | 实例宕机后调用方还在发请求,持续报错 |
面试答法:
Nacos 是 Spring Cloud Alibaba 体系中的核心基础设施,同时提供配置中心 和注册中心两个能力。配置中心解决了"配置分散、需重启生效、多环境混乱"的问题;注册中心解决了"服务地址写死、扩容不感知、故障不自动摘除"的问题。在我们项目中,用 Namespace 区分 dev/test/prod 环境,用服务名替代硬编码的 IP 地址调用。
Q2. Data ID、Group、Namespace 分别是什么?
知识点:配置的三维定位模型
从 Nacos 找一份配置,需要三个坐标同时匹配,缺一不可:
text
Namespace(命名空间) ── 最高隔离层
└── Group(分组) ── 次级隔离
└── Data ID ── 具体一份配置文件的名称
关键细节(面试加分点):
- Namespace 填写的是 Namespace ID(UUID 格式),不是控制台显示的名称
- 默认 Namespace 的 ID 是 空字符串
"",不是"public" - 三个坐标任一不匹配,静默返回空配置(不报错),这是调试时的常见陷阱
企业级设计示例:
text
Namespace: prod(ID: a1b2c3d4-xxxx)
├── Group: DEFAULT_GROUP
│ ├── Data ID: order-service.yml ← 订单服务主配置
│ └── Data ID: user-service.yml ← 用户服务主配置
└── Group: INFRA_GROUP
├── Data ID: common-db.yml ← 共享数据库配置
└── Data ID: common-redis.yml ← 共享 Redis 配置
面试答法:
Data ID 是一份配置文件的名称,Group 是业务分组(比如按业务线分),Namespace 是最高级别的隔离,通常用于区分环境。三个坐标同时匹配才能读到配置,有一个不对就读不到,而且不会报错,这是排查配置问题时要优先检查的点。
Q3. Nacos 和 Eureka、Apollo 有什么区别?
知识点:各组件的定位差异
| 维度 | Nacos | Eureka | Apollo |
|---|---|---|---|
| 配置中心 | ✅ | ❌ | ✅(更成熟) |
| 注册中心 | ✅ | ✅ | ❌ |
| 动态刷新 | ✅ | N/A | ✅(有审批流) |
| 灰度发布 | ✅(Beta发布) | ❌ | ✅(更完善) |
| 维护状态 | 活跃 | 已停止维护 | 活跃 |
| 生态 | Spring Cloud Alibaba | Spring Cloud Netflix | 独立 |
选型建议(面试高频考点):
- 新项目用 Spring Cloud Alibaba 体系 → 优先 Nacos(一套解决配置+注册)
- 团队重视配置审计、灰度、审批流 → 考虑 Apollo(配置治理更成熟)
- 多语言架构(Java/Go/Python 混合)→ 考虑 Consul
- 已有 Eureka 老项目 → 评估迁移成本(Nacos 有 Eureka 兼容模式)
二、初级项目题
Q4. Spring Boot 如何接入 Nacos 配置中心?
知识点:接入步骤与关键配置
接入分三个层面:依赖、配置文件、代码使用。
依赖管理(强调版本 BOM):
xml
<dependencyManagement>
<dependencies>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-alibaba-dependencies</artifactId>
<version>2023.0.1.2</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<dependencies>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
</dependency>
</dependencies>
application.yml 关键配置:
yaml
spring:
application:
name: order-service
config:
# optional: 表示 Nacos 不可用时允许降级,用本地配置启动
import: "optional:nacos:order-service.yml"
cloud:
nacos:
server-addr: 127.0.0.1:8848
config:
namespace: "" # Namespace ID(空=默认)
group: DEFAULT_GROUP
代码读取(推荐 @ConfigurationProperties):
java
@Component
@ConfigurationProperties(prefix = "order")
public class OrderProperties {
private int maxRetry = 3; // 提供默认值,防止 Nacos 不可用
private int timeout = 5000;
// getters/setters
}
面试答法:
接入步骤:引入
nacos-configstarter,配置 server-addr 和 spring.config.import 声明要拉取的 Data ID,然后用@ConfigurationProperties读取配置。特别要注意版本匹配,用 Spring Cloud Alibaba BOM 统一管理,不要手动指定版本。
Q5. 配置修改后为什么没有动态刷新?
知识点:动态刷新的必要条件
动态刷新需要以下条件同时满足:
text
条件1: 配置已发布(不是保存,是发布)
条件2: Data ID + Group + Namespace 完全匹配
条件3: Bean 支持刷新(@ConfigurationProperties 或 @RefreshScope)
条件4: 刷新的配置项不是"启动时固化"的属性
排查清单(按频率排序):
| 排查点 | 排查方法 |
|---|---|
| ① 是否点击了「发布」 | 控制台查看配置历史,确认有新版本 |
| ② Data ID 是否完全一致 | 比对应用日志中加载的 Data ID |
| ③ Namespace ID 是否正确 | Namespace 填的是 ID(UUID)不是名称 |
| ④ Bean 是否有刷新支持 | 检查是否有 @ConfigurationProperties 或 @RefreshScope |
| ⑤ 字段是否是 final | final 字段无法被刷新 |
| ⑥ 是否是不可刷新的属性 | server.port、datasource.url 等启动固化属性 |
常见误区:
java
// ❌ 没有任何刷新机制,永远不会更新
@Value("${order.timeout}")
private int timeout;
// ✅ @ConfigurationProperties 自动支持刷新
@ConfigurationProperties(prefix = "order")
public class OrderProperties {
private int timeout;
}
// ✅ @Value 需要配合 @RefreshScope
@RestController
@RefreshScope
public class OrderController {
@Value("${order.timeout}")
private int timeout;
}
Q6. Nacos 注册成功,但 Consumer 调用失败,怎么排查?
知识点:服务发现的作用域与网络可达性
服务注册成功只说明 Provider 和 Nacos 之间通了,调用失败可能有以下原因:
系统化排查流程:
text
第一步:确认服务在 Nacos 中是健康的
→ 控制台查看服务详情,实例状态是否为"上线"
第二步:确认 Namespace + Group 一致
→ Consumer 的 namespace/group 必须与 Provider 完全相同
→ 这是最常见的原因!
第三步:确认 Provider 注册的 IP 对 Consumer 可达
→ 控制台查看 Provider 注册的 IP
→ curl http://{provider-ip}:{port}/actuator/health
第四步:确认服务名拼写正确
→ @FeignClient(name) 必须与 spring.application.name 完全一致
第五步:确认 LoadBalancer 依赖存在
→ OpenFeign 需要 spring-cloud-starter-loadbalancer
面试答法:
排查顺序是:先看 Nacos 控制台实例是否健康,再确认 Namespace 和 Group 是否一致(这是最常见原因),然后检查 Provider 注册的 IP 是否对 Consumer 网络可达,最后检查 Feign 的服务名是否拼写正确。
Q7. 临时实例和永久实例有什么区别?
知识点:两种实例模型的设计意图
| 维度 | 临时实例(默认) | 永久实例 |
|---|---|---|
| 配置 | ephemeral: true |
ephemeral: false |
| 心跳方 | 客户端主动发心跳 | 服务端主动探测 |
| 健康判断 | 客户端15秒未心跳→不健康,30秒→删除 | 服务端探测失败→标记不健康,不自动删除 |
| 下线行为 | 心跳停止后自动摘除 | 需手工注销 |
| 适用场景 | Spring Boot 弹性微服务(推荐) | 静态服务、第三方数据库等 |
为什么推荐临时实例:
- 服务崩溃 → 心跳停 → Nacos 30秒内自动摘除 → Consumer 不再调用
- 符合云原生弹性扩缩容场景,实例随时可以创建和销毁
- 无需手工维护注册表
三、中级原理题
Q8. Nacos 配置中心的动态刷新原理是什么?
知识点:长轮询机制详解
很多人以为是服务端主动推送,实际上是客户端长轮询:
text
客户端定期发起 HTTP 请求(携带当前所有配置的 MD5)
│
└─► 服务端检查 MD5 是否有变化
├── 无变化 → 挂起请求,最多等待 30 秒后返回
└── 有变化 → 立即返回变更的 Data ID 列表
客户端收到响应后:
1. 重新拉取变更配置的完整内容
2. 更新本地缓存文件
3. 发布 Spring RefreshEvent
4. 立即发起下一轮长轮询
为什么用长轮询而非 WebSocket 推送:
| 对比维度 | 长轮询 | WebSocket 推送 |
|---|---|---|
| 防火墙/Nginx 兼容性 | ✅ HTTP 无感通过 | ⚠️ 部分防火墙拦截 |
| 服务端重启后重连 | ✅ 客户端自动重试 | 需要重连机制 |
| 大规模连接管理 | ✅ 连接数可控 | 长连接资源消耗大 |
面试答法:
Nacos 配置刷新是客户端长轮询,不是服务端推送。客户端定时(最长30秒超时)向服务端发请求,携带当前配置的 MD5。如果配置没变化,服务端挂起请求等待;一旦配置发布,立即返回变更的 Data ID 列表,客户端重新拉取配置,触发 Spring 的 RefreshEvent,从而刷新 @ConfigurationProperties 的属性。
Q9. Nacos 服务注册和服务发现的完整流程?
知识点:注册发现全链路
Provider 侧注册流程:
text
应用启动
→ 读取 spring.application.name、端口、Namespace、Group、元数据
→ 调用 Nacos Naming Service 注册实例
→ 开启心跳线程(临时实例,默认每 5 秒发一次)
运行中
→ Nacos 超过 15 秒未收到心跳 → 标记不健康
→ Nacos 超过 30 秒未收到心跳 → 删除实例
应用关闭
→ 优雅关闭:主动注销实例(推荐)
→ 强制关闭:等心跳超时被动删除(最多30秒延迟)
Consumer 侧发现流程:
text
应用启动
→ 从 Nacos 拉取订阅服务的实例列表
→ 缓存到本地(InstancesChangeEvent 更新缓存)
调用时
→ 查本地实例缓存(优先,避免每次查 Nacos)
→ LoadBalancer 按策略选一个健康实例
→ 替换服务名为 IP:Port,发起 HTTP 请求
实例变化时(Nacos 2.x)
→ Nacos Server 通过 gRPC 主动推送变更通知
→ Consumer 更新本地实例缓存
Q10. Nacos 的本地缓存有什么作用?
知识点:高可用降级设计
Nacos 客户端在以下路径保存配置快照:
text
{user.home}/nacos/config/
文件命名:{serverAddr}@{namespace}#{group}#{dataId}
例如:127.0.0.1_8848@#DEFAULT_GROUP#order-service.yml
作用(面试加分点):
text
场景1:Nacos Server 短暂宕机
→ 已运行的服务从本地缓存读取上一次成功拉取的配置
→ 服务不受影响(降级运行)
场景2:应用重启时 Nacos 不可用
→ 使用 optional: 前缀声明的配置,从本地缓存文件加载
→ 服务可以启动(使用快照)
场景3:网络分区
→ 本地缓存保证服务发现数据不会因为短暂断网而丢失
生产注意(Kubernetes 环境):
容器重启后本地缓存目录会丢失。如果重启时 Nacos 也恰好不可用,且配置声明为必须(无 optional:),应用将启动失败。
建议:
- 重要配置的 import 都加
optional:前缀 - 代码中为配置属性设置合理默认值
Q11. Nacos 注册中心的心跳机制是怎么工作的?
知识点:心跳参数与容错设计
yaml
spring:
cloud:
nacos:
discovery:
heart-beat-interval: 5000 # 客户端心跳间隔(毫秒),默认5000
heart-beat-timeout: 15000 # 服务端判断不健康的超时(毫秒),默认15000
ip-delete-timeout: 30000 # 服务端删除实例的超时(毫秒),默认30000
心跳生命周期:
text
0s → Provider 注册,开始每5秒发心跳
5s → 心跳正常,状态:健康
15s → 停止发心跳(宕机/网络中断)
15+15=30s → 超过15s未收到心跳 → Nacos 标记实例为不健康
30+30=60s → 超过30s未收到心跳 → Nacos 删除实例
调优建议:
| 场景 | 建议 |
|---|---|
| 需要快速感知故障 | 缩短 heart-beat-timeout(注意增加 Nacos 服务端压力) |
| 网络抖动频繁(实例被误删) | 适当延长 heart-beat-timeout |
| 大量实例(Nacos 压力大) | 适当延长 heart-beat-interval |
四、高级设计题
Q12. 生产环境 Nacos 应该如何部署?
知识点:高可用集群架构
最小生产集群(3节点):
text
┌──────────────────┐
外部 │ Nginx / LB │ 统一入口(8848)
客户端 └────┬──────┬──────┘
│ │
┌─────▼──┐ ┌─▼──────┐ ┌────────┐
│ Nacos1 │ │ Nacos2 │ │ Nacos3 │
└────┬───┘ └───┬────┘ └───┬────┘
└─────────┼──────────┘
│
┌────▼─────┐
│ MySQL │(持久化配置数据)
└──────────┘
为什么需要奇数节点:Raft 协议需要多数派(>N/2)才能选主。3节点容忍1个故障,5节点容忍2个故障。偶数节点容错率不增加,浪费资源。
关键配置:
properties
# 每个节点的 application.properties
nacos.standalone=false
spring.datasource.platform=mysql
db.url.0=jdbc:mysql://mysql:3306/nacos_config?...
nacos.core.auth.enabled=true
# Token 密钥必须自定义(默认值有安全漏洞)
nacos.core.auth.plugin.nacos.token.secret.key=<Base64随机密钥>
生产安全清单:
| 项目 | 要求 |
|---|---|
| 开启认证 | nacos.core.auth.enabled=true |
| 修改默认密码 | nacos/nacos 的默认账号必须修改 |
| 自定义 Token 密钥 | 不能使用默认密钥,否则有安全漏洞 |
| 控制台不暴露公网 | 通过 Nginx ACL 或安全组限制访问来源 |
| MySQL 高可用 | 配置主从或 MGR,单点 MySQL 是隐患 |
| 节点间端口开放 | 7848/9849 只在节点间开放 |
Q13. 如何设计公司的 Nacos 配置规范?
知识点:企业级配置治理
Namespace 规划(最重要,后期迁移成本极高):
text
dev → 开发环境(开发人员可随意修改)
test → 测试环境(测试和开发可修改)
staging → 预发布环境(受控修改,需 TL 审批)
prod → 生产环境(严格权限,必须走审批流 + 灰度)
Group 规划:
text
DEFAULT_GROUP → 各服务的主配置
INFRA_GROUP → 公共基础设施配置(DB/Redis/MQ 连接信息)
FEATURE_GROUP → 功能开关配置(适合频繁动态刷新)
Data ID 规范:
text
✅ order-service.yml ← 应用主配置(与 spring.application.name 一致)
✅ common-db.yml ← 公共数据库配置(放 INFRA_GROUP)
✅ feature-toggle.yml ← 开关配置(放 FEATURE_GROUP,频繁变更)
❌ order-service-prod.yml ← 禁止在 Data ID 中加环境后缀(用 Namespace 区分)
生产变更流程:
text
1. 开发提交 MR(说明变更内容和影响面)
2. 技术负责人审批
3. staging 环境先验证
4. 生产用 Beta 发布(指定灰度 IP,观察5-10分钟)
5. 无异常后点击「停止Beta」全量发布
6. 记录变更日志(时间/操作人/内容/回滚方案)
Q14. Nacos 宕机后,业务服务还能运行吗?
知识点:故障影响面分析
已运行的服务(最常见场景):
text
配置中心:
已拉取的配置 → 内存中正常使用 ✅
新配置发布 → 客户端感知不到 ❌
应用重启 → 从本地缓存加载(optional: 声明的) ⚠️
注册中心(临时实例):
现有实例列表 → Consumer 本地缓存中正常使用 ✅
新实例上线 → Consumer 感知不到 ❌
实例心跳 → 客户端继续发,但无人响应;Nacos 恢复后自动恢复 ✅
结论 :已运行的服务可以在 Nacos 宕机后短期内(分钟级)正常运行,但无法感知变更,且新应用启动会受影响。
面试答法:
已运行的服务可以依赖本地配置缓存和实例列表缓存继续运行,不会立即崩溃。但新的配置发布不会被感知,新实例上线也不会被发现,首次启动的新应用可能因拉不到配置而失败(除非用 optional: 声明)。所以生产不能依赖单节点 Nacos,必须部署 3 节点以上集群。
Q15. 配置发布错误导致故障,如何快速恢复?
知识点:配置回滚与应急处理
分钟级恢复流程:
text
1. 确认影响范围(哪个 Namespace/Group/Data ID 的变更导致的)
2. Nacos 控制台 → 配置详情 → 历史版本
3. 找到上一个正常版本,点击「回滚」
4. 验证关键服务是否恢复(查日志、检查核心接口)
5. 检查是否有实例使用了本地缓存(未感知到新配置)
Nacos 控制台历史版本操作:
text
配置管理 → 选中配置 → 更多 → 历史版本
→ 查看变更记录(时间、操作人、内容对比)
→ 选择正常版本 → 回滚
事后改进措施:
| 改进项 | 说明 |
|---|---|
| 配置格式校验 | 发布前用 YAML Lint 检查格式 |
| 灰度发布 | 重要配置先 Beta 发布到少量实例 |
| 变更审批 | 生产配置必须经过 TL 审批 |
| 回滚演练 | 定期演练配置回滚,验证流程有效 |
| 配置备份 | 通过 Open API 定期备份配置到 Git |
五、专家级追问题
Q16. Nacos 集群节点宕机一半,还能用吗?
知识点:CP(Raft)和 AP(Distro)的容错边界
这道题需要分模块回答:
| 节点总数 | 宕机数量 | 配置中心(CP/Raft) | 注册中心临时实例(AP/Distro) |
|---|---|---|---|
| 3 | 1 | ✅ 可用(多数派 2/3) | ✅ 可用 |
| 3 | 2 | ❌ 不可写(无多数派) | ✅ 存活节点仍可服务 |
| 5 | 2 | ✅ 可用(多数派 3/5) | ✅ 可用 |
| 5 | 3 | ❌ 不可写(无多数派) | ✅ 存活节点仍可服务 |
关键补充:
- 配置中心不可写不等于不可读:客户端已拉取的配置在内存中,正常运行
- 注册中心在 AP 模式下,即使半数以上节点宕机,剩余节点仍可处理注册和查询
- 这就是为什么 Nacos 对两种模块分别选择 CP 和 AP
面试答法:
要分模块回答。配置中心用 Raft(CP),需要多数派节点存活才能写入,3节点宕1个没问题,宕2个写入失败但读取有缓存。注册中心临时实例用 Distro(AP),只要有节点存活就能提供服务,可用性更高。所以生产推荐5节点,可以容忍2个节点同时故障。
Q17. 为什么配置中心用 CP,注册中心用 AP?
知识点:CAP 定理在 Nacos 的工程权衡
配置中心选 CP(Raft)的原因:
配置是"指令"------数据库地址、限流阈值、功能开关。如果两个节点配置不一致:
- 服务 A 拿到
maxRetry=3,服务 B 拿到maxRetry=10 - 业务逻辑不一致,可能引发严重事故
所以配置中心宁可短暂不可用,也要保证一致性(CP)。
注册中心(临时实例)选 AP(Distro)的原因:
实例信息是"状态"------某个 IP:Port 是否健康。如果网络分区时拒绝服务:
- Consumer 无法查询实例列表
- 整个调用链中断
拿到稍旧的实例列表(比如有一个已经不健康的实例),最多触发一次调用失败+重试,危害远小于整个注册发现不可用。
所以注册中心宁可返回稍旧数据,也要保证可用性(AP)。
Raft 协议关键点:
text
选主:Follower 超时未收到 Leader 心跳 → 发起选举 → 多数派投票 → 成为 Leader
写入:Leader 写入 → 并行复制给 Follower → 多数确认 → 提交 → 通知客户端
容错:N 个节点可容忍 (N-1)/2 个故障
Distro 协议关键点:
text
每个节点都可以处理写请求(注册/注销)
节点负责部分实例的心跳检测(责任节点)
数据异步同步到其他节点(最终一致)
节点故障时,其他节点接管其实例
Q18. Nacos 灰度配置发布是如何实现的?
知识点:Beta 发布机制
Nacos 2.x 支持 Beta 发布(灰度发布):
text
正常发布:配置变更 → 推送给所有订阅该 Data ID 的客户端
Beta 发布:配置变更 → 只推送给指定 IP 列表的客户端
其他客户端继续使用旧配置
全量发布:停止 Beta → 新配置推送给所有客户端
控制台操作步骤:
text
1. 编辑配置 → 点击「Beta发布」(不是「发布」)
2. 输入灰度 IP:192.168.1.100,192.168.1.101
3. 发布后观察灰度实例日志和业务指标
4. 确认无误 → 点击「停止Beta」完成全量发布
CI/CD 集成(Open API 方式):
bash
# 获取认证 Token
TOKEN=$(curl -s -X POST "http://nacos:8848/nacos/v1/auth/login" \
-d "username=admin&password=yourpassword" | jq -r '.accessToken')
# Beta 发布(指定灰度 IP)
curl -X POST "http://nacos:8848/nacos/v1/cs/configs" \
-H "Authorization: Bearer ${TOKEN}" \
-d "dataId=order-service.yml&group=DEFAULT_GROUP&namespace=prod-ns-id&content=$(cat order-service.yml)&betaIps=192.168.1.100"
# 停止 Beta(全量发布)
curl -X DELETE "http://nacos:8848/nacos/v1/cs/configs?beta=true\
&dataId=order-service.yml&group=DEFAULT_GROUP&namespace=prod-ns-id" \
-H "Authorization: Bearer ${TOKEN}"
适用场景:
- 配置变更影响面大(如数据库连接参数)
- 配置变更可能有业务风险,需要先验证少量实例
- 多节点服务的滚动配置更新
Q19. 生产环境 Nacos 监控应该关注哪些指标?
知识点:可观测性体系
Nacos 2.x 支持 Prometheus 格式指标,暴露地址:
text
http://nacos-node:8848/nacos/actuator/prometheus
关键告警指标:
| 指标 | 含义 | 告警阈值建议 |
|---|---|---|
nacos_monitor_ip_count |
注册实例总数 | 骤降50%告警 |
nacos_monitor_service_count |
已注册服务数 | 突变告警 |
http_server_requests_seconds{p99} |
接口 P99 延迟 | 超过500ms告警 |
jvm_memory_used_bytes |
JVM 内存使用 | 超过limit 80%告警 |
jvm_gc_pause_seconds{p99} |
GC 停顿时间 | 超过200ms告警 |
nacos_naming_client_subscribe_count |
订阅连接数 | 异常升高可能内存泄漏 |
Prometheus 采集配置:
yaml
scrape_configs:
- job_name: 'nacos-cluster'
metrics_path: '/nacos/actuator/prometheus'
static_configs:
- targets:
- 'nacos-1:8848'
- 'nacos-2:8848'
- 'nacos-3:8848'
推荐 Grafana Dashboard :导入 ID 17093(Nacos 官方提供)。
Q20. 如何防止 Nacos 配置被误改?
知识点:配置安全与权限治理
技术层面:
text
1. 开启认证(nacos.core.auth.enabled=true)
2. 按 Namespace 设置访问权限(生产 Namespace 只允许运维角色)
3. 控制台不暴露公网(安全组 + Nginx ACL 限制来源 IP)
4. 自定义 Token 密钥(不使用默认密钥)
流程层面:
text
1. 生产配置发布必须走审批(至少2人确认)
2. 变更前在 staging 验证
3. 变更时使用 Beta 发布灰度
4. 变更后监控关键指标5-10分钟
5. 保留完整变更记录(Nacos 历史版本 + 外部 Git 备份)
定期备份配置:
bash
#!/bin/bash
# backup-nacos-configs.sh
TOKEN=$(curl -s -X POST "http://nacos:8848/nacos/v1/auth/login" \
-d "username=admin&password=${NACOS_PASS}" | jq -r '.accessToken')
# 获取所有配置列表
curl -s "http://nacos:8848/nacos/v1/cs/configs?search=accurate&dataId=&group=&pageNo=1&pageSize=100" \
-H "Authorization: Bearer ${TOKEN}" > nacos-configs-$(date +%Y%m%d).json
# 提交到 Git 备份
git add . && git commit -m "nacos backup $(date +%Y-%m-%d)" && git push
六、专家级底层原理题
Q21. Nacos 2.x 和 1.x 的核心区别是什么?
知识点:gRPC 长连接 vs HTTP 长轮询
| 维度 | Nacos 1.x | Nacos 2.x |
|---|---|---|
| 通信协议 | HTTP 长轮询(配置)/ HTTP 心跳(注册) | gRPC 长连接(配置+注册统一) |
| 连接端口 | 8848(HTTP) | 8848(HTTP)+ 9848(gRPC 客户端) |
| 配置推送延迟 | 最长30秒(长轮询超时) | 秒级(长连接即时推送) |
| 服务端推送 | 无法主动推送,依赖客户端轮询 | 可以主动推送服务实例变更 |
| 性能 | 大量客户端时连接数大 | gRPC 多路复用,性能更好 |
升级注意事项:
- 2.x 客户端必须能访问服务端的 9848 端口(gRPC),仅开放 8848 会导致连接失败
- Kubernetes 部署时 Service 必须同时暴露 8848 和 9848
Q22. 如果让你从零搭建 Nacos 集群,你会怎么做?
知识点:生产集群搭建步骤
第一步:初始化 MySQL 数据库
sql
-- 创建数据库
CREATE DATABASE nacos_config CHARACTER SET utf8 COLLATE utf8_general_ci;
-- 导入官方建表语句(下载地址:Nacos GitHub releases)
-- mysql -u nacos -p nacos_config < nacos-mysql.sql
第二步:配置每个节点的 application.properties
properties
spring.datasource.platform=mysql
db.num=1
db.url.0=jdbc:mysql://mysql-host:3306/nacos_config?characterEncoding=utf8&connectTimeout=1000&socketTimeout=3000&autoReconnect=true&useSSL=false
db.user.0=nacos
db.password.0=nacos_password
# 开启认证
nacos.core.auth.enabled=true
nacos.core.auth.plugin.nacos.token.secret.key=$(openssl rand -base64 32)
nacos.core.auth.server.identity.key=serverIdentity
nacos.core.auth.server.identity.value=$(openssl rand -hex 8)
第三步:配置集群节点列表 cluster.conf
text
192.168.1.10:8848
192.168.1.11:8848
192.168.1.12:8848
第四步:配置 Nginx 负载均衡
nginx
upstream nacos_cluster {
server 192.168.1.10:8848;
server 192.168.1.11:8848;
server 192.168.1.12:8848;
}
server {
listen 8848;
location / {
proxy_pass http://nacos_cluster;
proxy_set_header Host $host;
proxy_connect_timeout 5s;
}
}
第五步:启动验证
bash
# 每个节点执行
sh bin/startup.sh
# 验证集群状态(任一节点)
curl http://localhost:8848/nacos/v1/ns/operator/servers
# 返回的 servers 数组中应有3个节点,status 均为 UP
七、项目经验表达模板
面试中如何表达项目经验
标准话术(可直接背诵):
text
我们项目使用 Nacos 同时做配置中心和注册中心。
配置方面:
- 用 Namespace 区分 dev/test/staging/prod 四个环境
- 用 Group 区分业务线(DEFAULT_GROUP 放各服务主配置,INFRA_GROUP 放公共组件配置)
- 每个微服务有独立的 Data ID,命名规范为 {服务名}.yml
- 数据库、Redis、MQ 等公共配置抽取成独立 Data ID 共享
注册中心方面:
- Provider 启动自动注册到 Nacos,Consumer 通过 OpenFeign + 服务名调用
- 实例元数据中打了 version 标签,用于金丝雀发布流量控制
生产运维方面:
- 3节点 Nacos 集群,后端接 MySQL 主从,前端挂 Nginx
- 开启认证,自定义 Token 密钥,控制台只对内网开放
- 生产配置发布必须走审批,重要配置先 Beta 发布到灰度实例
- 出现误配置时通过历史版本界面一键回滚,最快2分钟恢复
八、面试自测表
| 题目 | 能否1分钟讲清 | 能否结合项目 | 能否回答追问 |
|---|---|---|---|
| Nacos 是什么,解决什么问题 | |||
| Data ID/Group/Namespace 区别 | |||
| 配置中心接入步骤 | |||
| 动态刷新不生效排查 | |||
| 服务注册成功但调用失败排查 | |||
| 临时实例 vs 永久实例 | |||
| 长轮询原理 | |||
| CP/AP 选择原因 | |||
| 生产集群部署方案 | |||
| 配置误发故障恢复 | |||
| Nacos 2.x vs 1.x | |||
| 灰度配置发布 | |||
| 生产监控指标 |