最近一直在折腾本地调试 Nacos 集群,过程中踩了不少坑,尤其是“用 IDEA 源码启动集群”和“把 dashboard 控制台单独配置出来访问”这两件事,网上资料讲得都不够细。最近我完整跑通了一条路:IDEA 里启动源码版 Nacos 三节点集群,集群全部注册成功,dashboard 也能正常管理配置和节点。这篇文章就把我的完整配置、端口规划原理和踩坑记录写下来。
这篇内容适合这几类人:想读 Nacos 源码但又不满足于单机跑的开发者;需要在本地模拟生产环境集群做二次开发的工程师;以及被 Nacos 2.x 的端口偏移、Derby 锁库、控制台 403 等问题折磨过的朋友。我会尽量把每一步的“为什么”也讲清楚,而不是只给一个能跑的参数组合。
1. 为什么我把 Nacos 源码拉下来跑集群,而不是直接用安装包
先别急着配参数,聊清楚动机。
直接用官方发行版启动确实容易,下载解压、改一下 cluster.conf、然后 startup.sh -p 指定端口就能跑。但如果你和我一样需要改点源码、加日志、断点调试,这就行不通了。发行版里的代码是编译后的 class 文件,Idea 里断点打上去完全没用。我这次需要观察配置变更在集群节点间的同步行为,还要临时改动认证逻辑,所以必须是源码启动。
源码启动还有一个隐藏好处:能直观看到 Nacos 内部模块是怎么组织的。拉下来之后你会发现几个关键模块:
- console:控制台前端资源、接口入口,同时也是 Spring Boot 的启动模块
- naming:服务注册与发现实现
- config:配置管理实现
- core:通用能力,比如事件通知、集群成员管理、一致性协议封装
- consistency:一致性协议,2.x 里包含 JRaft 相关逻辑
启动类就落在 console 模块里,主类名是com.alibaba.nacos.Nacos。你在 IDEA 里新建 Spring Boot 运行配置时,直接指向这个类即可。源码版本我选的是 2.2.x 分支,3.x 也类似,但 2.2.x 目前用得最多,社区资料最全,不要轻易上 3.x 做源码调试,有些模块拆得更细,配置方式有差别。
拿到源码后先执行一次根目录编译:
mvn clean install -DskipTests -q这一步很重要。第一次直接用 IDEA 启动源码,容易因为某些子模块没有安装到本地 Maven 仓库而报Cannot resolve ...。先把整个项目 install 一遍,后续启动就很顺。
2. 端口规划与集群底层原理:这部分不看,启动必踩坑
2.1 三节点端口不能选连续的,注意 1000/1001 偏移
Nacos 2.x 和 1.x 最大的一个区别是:服务端不仅监听 HTTP 端口,还会在这个端口基础上自动偏移出 gRPC 端口。
具体规则是:
- main port = HTTP 端口 + 1000
- client port = HTTP 端口 + 1001
如果你选 8841、8842、8843 这种连续端口,就会出现端口重叠:
| 节点端口 | gRPC 主端口 | gRPC 客户端端口 |
|---|---|---|
| 8841 | 9841 | 9842 |
| 8842 | 9842 | 9843 |
| 8843 | 9843 | 9844 |
能看到 8842 的 gRPC 主端口 9842 和 8841 的 gRPC 客户端端口 9842 直接冲突。启动后日志会报Address already in use,而且由于端口偏移是自动计算出来的,你不会第一时间想到是这个原因。
我最终本地调试用的是 8841、8843、8845 这套端口,相邻间隔为 2,避免位移后的端口重叠。也可以选 8848、8868、8888 这种像官方风格的端口,只要保证相邻节点差至少 2 就行。
对应分配的 gRPC 端口是:
| 节点 | HTTP 端口 | gRPC 主端口 | gRPC 客户端端口 |
|---|---|---|---|
| node-8841 | 8841 | 9841 | 9842 |
| node-8843 | 8843 | 9843 | 9844 |
| node-8845 | 8845 | 9845 | 9846 |
在本地单机调三节点时,这个规划越早确定越好,不然后面跑起来再改端口,所有数据目录、日志、集群地址都要重新对齐。
2.2 为什么至少要三节点,两个节点行不行
Nacos 集群节点数下限是三,这背后是一致性算法的要求。
Nacos 2.x 中,配置中心的数据一致性依赖 JRaft,也就是 Raft 协议。Raft 的选主需要多数派:集群里超过一半的节点存活,才能选出 Leader、才能对外提供服务。两节点集群“多数派”就是 2,任何一台机器故障,存活节点数只有 1,无法组成多数派,集群立刻只读甚至不可用。
三节点集群允许挂一台,这是最小的容错规模。本地模拟集群,我建议就跑标准三节点,别图省事跑两个节点。你后面测试故障转移的时候会感谢这个决定。
Raft 在节点间同步的是配置数据这类 CP 数据;而注册中心的服务实例数据是 AP 模型,走的是 Distro 协议。所以集群节点之间不是简单的主从复制,而是分协议处理的。源码调试时你会在日志里看到两类集群状态:
- 配置一致性相关的选主日志
- 服务健康检查相关的同步日志
一开始看到日志里既有 Leader 又有健康检查同步,不要觉得混乱,这是 Nacos 2.x 的正常现象。
2.3 数据目录必须隔离,Derby 锁库是最典型的本地集群事故
Nacos 使用内嵌 Derby 作为默认存储时,每个节点都有自己独立的数据库文件。如果同一台机器上启动多个节点,并且没有指定各自独立的数据目录,那么后启动的节点会去争用同一个 Derby 数据文件,直接启动失败。
日志里会出现类似database in use或者Fail to lock Derby这样的信息。
解决方法是给每个节点指定独立的nacos.home或nacos.data.dir。我的做法是在 IDEA 的 VM options 里给三个节点分别指定不同的 home 目录:
-Dnacos.home=/data/nacos-cluster/node-8841 -Dnacos.home=/data/nacos-cluster/node-8843 -Dnacos.home=/data/nacos-cluster/node-8845这样 data、logs、conf 都会天然隔离,不需要额外处理日志目录。建议不要只设nacos.data.dir而忽略 logs,同一份日志目录下三个节点互相写,出了问题根本分不清日志来自哪个节点。
2.4 节点发现配置:用 NACOS_SERVERS 还是 cluster.conf
源码方式启动集群,节点发现有两种常见配置:
- 环境变量
NACOS_SERVERS,多个地址用逗号分隔 - 配置文件
conf/cluster.conf
我个人在 IDEA 里调试时推荐环境变量方式,因为不需要去动源码目录下的配置文件,也避免因为nacos.home指向不同而产生 conf 不统一的问题。
在 IDEA 的 Run Configuration 里,Environment variables 一栏写:
NACOS_SERVERS=127.0.0.1:8841,127.0.0.1:8843,127.0.0.1:8845注意这里的地址是 HTTP 端口,不是 gRPC 偏移端口。集群启动后,每个节点会拿着这份列表去和另外两个节点建立连接,并交换成员信息。
3. IDEA 里创建三个启动入口的完整配置过程
3.1 新建 Spring Boot 运行配置,而不是 Application 配置
在 IDEA 里启动 Nacos 源码,推荐用 Spring Boot 类型的 Run Configuration。
操作路径:Run -> Edit Configurations -> 左上角 + -> Spring Boot。Name 我建议直接用节点名,比如nacos-node-8841,这样三个配置一眼就能区分。
Main class 填com.alibaba.nacos.Nacos,如果 Idea 没有自动识别,先确认左边选择的是nacos-console模块。
这里有个小细节:如果模块下拉列表里找不到nacos-console,说明项目还没有完整导入 Maven 模块。回到 Maven 面板刷新一下,等索引完成后再看。不要手动指定其他模块的启动类,Nacos 的主启动类确实在 console 模块,其他模块只会启动一部分功能。
3.2 三个节点的 VM options 和环境变量完整配置
我最终用的三套配置是下面这样的,直接复制改路径就行。
node-8841:
# VM options -Dserver.port=8841 -Dnacos.home=/data/nacos-cluster/node-8841 -Dnacos.server.ip=127.0.0.1 -Dnacos.core.auth.enabled=true -Dnacos.core.auth.plugin.nacos.token.secret.key=QmxvZ0NsdXN0ZXJLZXlBYjEyMzQ1Njc4OTBGR0hJSg==环境变量:
NACOS_SERVERS=127.0.0.1:8841,127.0.0.1:8843,127.0.0.1:8845node-8843:
-Dserver.port=8843 -Dnacos.home=/data/nacos-cluster/node-8843 -Dnacos.server.ip=127.0.0.1 -Dnacos.core.auth.enabled=true -Dnacos.core.auth.plugin.nacos.token.secret.key=QmxvZ0NsdXN0ZXJLZXlBYjEyMzQ1Njc4OTBGR0hJSg==环境变量同上。
node-8845:
-Dserver.port=8845 -Dnacos.home=/data/nacos-cluster/node-8845 -Dnacos.server.ip=127.0.0.1 -Dnacos.core.auth.enabled=true -Dnacos.core.auth.plugin.nacos.token.secret.key=QmxvZ0NsdXN0ZXJLZXlBYjEyMzQ1Njc4OTBGR0hJSg==环境变量同上。
3.3 每个参数为什么这么设置
这些参数是我从实际启动过程里确认过作用的,解释一下:
-Dserver.port是 Spring Boot 标准属性,决定 Nacos 对外 HTTP 端口。-Dnacos.home指定当前节点的工作目录,隔离数据和日志,避免 Derby 锁冲突。-Dnacos.server.ip在多网卡机器上特别重要。如果不固定成 127.0.0.1,Nacos 可能选到虚拟机网卡或者 Docker 网卡的地址,导致另外两个节点连不上。-Dnacos.core.auth.enabled=true开启鉴权,模拟生产环境行为。-Dnacos.core.auth.plugin.nacos.token.secret.key是 JWT 签名密钥。从 2.2.1 版本起,部分接口没配这个 key 会直接返回 403,而且必须是 Base64 编码后的字符串。上面那个值是我随便生成的样例,你替换成自己的即可。
生成你自己的 key 可以用一行命令:
echo -n "your-secret-key-at-least-32-bytes" | base643.4 启动时的内存参数建议
源码方式启动的 JVM 内存占用比发行版高不少,因为 IDE 本身还要跑一堆索引和编译。我建议给每个节点至少分配 512m 堆内存,三个节点同时在 IDEA 里跑的话,电脑内存 16G 起步才比较舒服。
同样在 VM options 里加上:
-Xms512m -Xmx512m -XX:MaxMetaspaceSize=512m如果机器内存紧张,可以一次只启动一个节点,等三个都起来了再做集群验证。
3.5 启动顺序有讲究吗
有,但不用太严格。
我的习惯是先启动 node-8841,让第一个节点以单成员模式启动完成初始化,再启动另外两个。后启动的节点会通过NACOS_SERVERS列表主动找到第一个节点,并触发集群成员变更,此时 node-8841 的日志里会出现成员变动的记录。
第一次启动会比较慢,因为 Derby 初始化、一致性协议启动、控制台资源加载都集中在这一阶段。看到类似Nacos started successfully in cluster mode的日志,才算这个节点启动完成。
4. Dashboard 控制台接入:集群起来了,管理入口怎么配
4.1 最直接的方式:直接访问任意节点的 /nacos
集群成功后,dashboard 不需要单独做任何配置。三个节点都已经内置了控制台,访问任意节点的 8841、8843 或 8845 端口,路径为/nacos就能打开登录页。
比如:
http://127.0.0.1:8841/nacos默认账号密码都是 nacos。如果你开启了鉴权,第一次登录建议修改默认密码。
打开后在“集群管理”菜单下进入“节点列表”,应该能看到三个节点都出现在列表里,并且有对应的 Raft 状态、Leader 标识、健康状态。这一步能通过,说明集群成员关系已经建立,配置同步和服务注册的基础链路没问题。
4.2 想把 dashboard 统一放到一个独立入口:nginx 反向代理
实际开发中,你通常不希望团队成员记住三个节点端口去找控制台,而是希望一个固定地址像http://127.0.0.1:8080/nacos就能访问。
这个需求用 nginx 反代就能实现,而不需要再启动一个“额外 Nacos 进程”。这是我要特别强调的一点:Nacos 官方并没有把 dashboard 拆成一个独立可部署的进程,控制台就是每个服务端节点的一部分。
我的 nginx 配置长这样:
upstream nacos_cluster { server 127.0.0.1:8841; server 127.0.0.1:8843; server 127.0.0.1:8845; } server { listen 8080; location /nacos/ { proxy_pass http://nacos_cluster/nacos/; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; } }这个配置把 dashboard 固定在了 8080 端口,并且三个节点做了轮询。因为控制台的接口是无状态的,轮询到任何一个节点都能正确操作集群。你发布配置时,写请求会被内部分发到对应的 Raft Leader 节点。
4.3 一个常见误区:不要单独启动“第四个进程”当 dashboard
我一开始也想过:既然有三个服务端节点,能不能单独再起一个进程只跑 dashboard,专门用来管理集群,避免 dashboard 的查询流量压到业务节点上?
实际上没有这个必要,而且很容易把自己绕进去。单独启动一个 console 模块的 Nacos 进程,它不是一个纯前端控制台,而是一个完整的服务端节点。如果你不对端口和集群配置做严格区分,它可能会尝试加入集群,变成一个四节点集群,或者因为数据目录、端口规划问题把整个集群搞乱。
正确的思路是:dashboard 就是把服务端已经内置的 Web 页面通过网关或反代暴露出来。想让它看起来像独立服务,用nginx的proxy_pass就够了。
我实测下来,反代方式访问控制台功能和直接访问节点没有任何差异,配置列表、服务列表、权重调整、命名空间管理都能正常操作。
5. 集群启动成功后的自检清单与故障排查思路
5.1 用 curl 做一次最小化集群验证
启动完成先不要急着登录控制台,我用几条命令做快速验证,确认集群确实在正常工作。
第一步,检查三个节点健康状态:
curl http://127.0.0.1:8841/nacos/v1/console/health/liveness curl http://127.0.0.1:8843/nacos/v1/console/health/liveness curl http://127.0.0.1:8845/nacos/v1/console/health/liveness正常会返回ok。这一步说明服务进程是活的,HTTP 端口和 gRPC 端口没有明显问题。
第二步,在 8841 上发布一条测试配置:
curl -X POST "http://127.0.0.1:8841/nacos/v1/cs/configs" \ --data-urlencode "dataId=cluster-test" \ --data-urlencode "group=DEFAULT_GROUP" \ --data-urlencode "content=hello nacos cluster"如果返回true,说明写入成功。如果开了鉴权,需要先在控制台登录并获得 accessToken,在 curl 命令里追加accessToken参数。本地调试不想带 token 的话,可以暂时把nacos.core.auth.enabled设为 false 再验证。
第三步,在 8843 节点读取这条配置:
curl "http://127.0.0.1:8843/nacos/v1/cs/configs?dataId=cluster-test&group=DEFAULT_GROUP"能读出hello nacos cluster,说明配置已经在集群内完成同步。如果这一关过了,集群核心功能基本没问题。
5.2 常见故障:先看日志再动手
我在调试过程中遇到过几个典型问题,都记录在这里。
| 现象 | 根本原因 | 解决方式 |
|---|---|---|
| 启动时报 Derby 锁库、database in use | 多个节点共用同一个数据目录 | 给每个节点设置独立-Dnacos.home或-Dnacos.data.dir |
| 报 Address already in use,且端口是 984x | HTTP 端口连续导致 gRPC 偏移端口重叠 | 节点端口间隔至少 2,比如 8841、8843、8845 |
| 节点启动成功,但控制台节点列表只有一个节点 | NACOS_SERVERS环境变量没设置或格式不对 | 确认环境变量填到 Run Configuration 的 Environment variables 一栏 |
| 节点日志中一直出现连接其他节点失败 | nacos.server.ip未固定,选到了虚拟网卡地址 | VM options 里显式加-Dnacos.server.ip=127.0.0.1 |
| 控制台接口返回 403 | 2.2.1 起的鉴权签名 key 未配置或 key 太短 | 配置-Dnacos.core.auth.plugin.nacos.token.secret.key,并保证长度 |
| 发布配置报错,提示仅 Leader 可写或集群不可用 | 节点未组成多数派,Raft 还没选出 Leader | 等待三个节点全部启动后检查节点列表,确认成员完整 |
排查思路比具体命令更值钱。我个人的习惯是先开logs/nacos.log,用关键词过滤ERROR、WARN、MEMBER、raft,一般能在 30 秒内定位问题方向。
5.3 判断集群是否真正成功的最终标准
控制台节点列表显示三个节点、Raft 状态正常、能够在不同节点间同步配置,这三项同时满足,才算真正跑通。
很多人看到三个节点都显示“UP”就以为成功了,但发布一条配置后,客户端在其他节点读不到,说明一致性协议没有正常工作。所以我强烈建议用上面的 curl 第二步和第三步做一次跨节点验证。这一步过了,集群才是真正意义上的可用状态。
最后再分享一个小技巧:本地调试时,我会单独开一个日志窗口实时跟踪某个节点的nacos.log,当发布配置或者注册服务时,能清楚看到数据在集群里的流转路径。比如配置发布后,观察非 Leader 节点如何转发写请求、Leader 如何提交日志、其他节点如何应用变更。这些在纯黑盒的发行版里是看不到的,也是我坚持源码启动集群的最大收获。