1. 为什么单机 Nacos 撑不住生产环境
1.1 从一次线上告警说起
去年帮一个朋友排查问题,他们团队做了一套微服务系统,注册中心用的是单机版 Nacos。上线头两个月一切正常,直到某个周五下午,运维例行重启了一台服务器做安全补丁更新,恰好那台机器上跑着 Nacos。结果整个服务集群在几分钟内开始大面积报错——服务间调用找不到实例,网关路由全部失效,十几个微服务像断了线的风筝。他们当时没有做集群,也没有做持久化外置,重启之后配置数据丢了一部分,恢复花了将近两个小时。
这件事让我意识到,很多团队在开发阶段用单机 Nacos 跑得很顺,就默认生产环境也能这么干。但注册中心和配置中心是整个微服务体系的基础设施,它一旦挂掉,所有依赖它的服务都会受到连锁影响。单机 Nacos 存在三个致命问题:单点故障导致服务不可用、数据存在内存或本地文件导致重启后可能丢失、无法水平扩展导致大规模服务注册时性能瓶颈明显。
所以这篇文章,我想把 Nacos 集群搭建这件事从头到尾讲透。不管你是刚接触 Nacos 的新手,还是已经用过单机版想升级到集群的开发者,我都会把每一步的操作、每一个参数的含义、每一个可能踩的坑说清楚。集群搭建本身不复杂,但细节很多,一个配置写错就可能导致节点起不来或者集群状态异常。
1.2 Nacos 集群的核心架构逻辑
在动手之前,先搞清楚 Nacos 集群是怎么工作的。Nacos 集群的核心分为两个层面:服务注册与发现和配置管理。
服务注册这块,Nacos 集群中每个节点都是对等的,客户端可以连接任意一个节点进行服务注册和发现。节点之间通过异步复制的方式同步服务实例信息。这意味着即使某个节点挂了,客户端切换到其他节点仍然能正常工作。
配置管理这块稍微复杂一些。Nacos 使用Raft 协议来保证配置数据的一致性。集群中会有一个 Leader 节点负责处理写请求,其他节点作为 Follower。当你通过某个节点发布配置时,如果这个节点不是 Leader,它会将请求转发给 Leader,由 Leader 完成写入后再同步到其他节点。这就是为什么 Nacos 集群建议部署奇数个节点——Raft 协议需要多数派投票,3 个节点允许挂 1 个,5 个节点允许挂 2 个,而 4 个节点也只能允许挂 1 个,从性价比来说奇数更合理。
另外,Nacos 集群必须搭配外部数据库使用,通常是 MySQL。单机模式下 Nacos 默认使用内嵌的 Derby 数据库,但 Derby 不支持集群模式下的数据共享。所以集群搭建的第一步,就是准备好一个所有节点都能访问的 MySQL 实例。
注意:Nacos 集群中的所有节点必须连接同一个 MySQL 数据库,且数据库需要提前建好对应的表结构。表结构 SQL 文件在 Nacos 安装包的
conf目录下,文件名是mysql-schema.sql。
2. 搭建前的环境准备与规划
2.1 节点规划与硬件要求
集群搭建最怕的就是没有提前规划好,做到一半发现端口冲突或者资源不够。我一般建议在动手之前先画一张表,把每个节点的信息列清楚。
以下是一个典型的 3 节点集群规划示例:
| 节点名称 | 角色 | 用途说明 |
|---|---|---|
| nacos-node1 | Leader(动态选举) | 注册中心 + 配置中心 |
| nacos-node2 | Follower | 注册中心 + 配置中心 |
| nacos-node3 | Follower | 注册中心 + 配置中心 |
硬件方面,每个 Nacos 节点建议至少分配2 核 CPU、4GB 内存。Nacos 本身是 Java 应用,JVM 调优很重要。如果服务实例数量在几百个以内,这个配置足够了。如果服务规模更大,比如上千个实例,建议每个节点 4 核 8GB 起步。
操作系统层面,Linux 是首选,推荐 CentOS 7+ 或 Ubuntu 20.04+。需要提前确认几件事:JDK 版本(Nacos 2.x 需要 JDK 8 或 JDK 11)、防火墙策略(需要开放 Nacos 使用的端口)、时钟同步(集群节点之间时间差不能太大,否则 Raft 选举可能出问题)。
2.2 端口占用与防火墙策略
Nacos 2.x 相比 1.x 在端口使用上有较大变化,这是很多人搭建集群时容易忽略的点。Nacos 2.x 除了传统的 HTTP 端口(默认 8848)外,还新增了 gRPC 通信端口。
具体来说,Nacos 2.x 默认使用以下端口:
- 8848:HTTP 端口,用于控制台访问和 OpenAPI
- 9848:gRPC 客户端通信端口,供 Nacos 客户端连接使用
- 9849:gRPC 服务端通信端口,用于集群节点之间的数据同步
- 7848:Raft 通信端口,用于集群选举和数据一致性
这四个端口缺一不可。很多人在搭建集群后发现节点之间无法通信,八成是防火墙没放行 9849 和 7848 端口。我个人的习惯是在搭建之前就把这些端口的防火墙规则全部配好,省得后面排查半天。
# 以 firewalld 为例,放行 Nacos 所需端口 sudo firewall-cmd --permanent --add-port=8848/tcp sudo firewall-cmd --permanent --add-port=9848/tcp sudo firewall-cmd --permanent --add-port=9849/tcp sudo firewall-cmd --permanent --add-port=7848/tcp sudo firewall-cmd --reload提示:如果你的环境使用的是 iptables 或者云服务商的安全组,对应的配置方式不同,但核心原则一样——这四个端口必须在所有节点之间双向放行。
2.3 MySQL 数据库准备
前面说了,Nacos 集群必须使用外部 MySQL。MySQL 版本建议 5.7 或 8.0,两者都经过大量生产验证。数据库的准备工作分三步:创建数据库、导入表结构、创建专用账号。
-- 创建 nacos 数据库 CREATE DATABASE nacos_cluster DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci; -- 创建专用用户并授权(不要直接用 root) CREATE USER 'nacos_user'@'%' IDENTIFIED BY 'YourStrongPassword123'; GRANT ALL PRIVILEGES ON nacos_cluster.* TO 'nacos_user'@'%'; FLUSH PRIVILEGES;然后导入 Nacos 提供的表结构文件。这个文件在 Nacos 安装包的conf/mysql-schema.sql。导入完成后,数据库里应该有十几张表,包括config_info、config_info_beta、his_config_info、tenant_info等。
注意:MySQL 数据库的字符集必须是 utf8mb4,否则配置内容中包含特殊字符时可能乱码。另外,数据库连接池的配置也需要关注,后面在
application.properties中会详细说明。
3. Nacos 集群搭建全流程实操
3.1 安装包下载与目录规划
Nacos 的安装包可以从官方渠道获取,选择稳定版本即可。我一般推荐使用 2.2.x 或 2.3.x 的稳定版本,功能完善且社区文档丰富。下载完成后,在每个节点上解压到统一的目录,比如/opt/nacos。
# 在每个节点上执行 cd /opt tar -zxvf nacos-server-2.3.0.tar.gz mv nacos nacos-cluster cd nacos-cluster ls -la解压后的目录结构大致如下:
nacos-cluster/ ├── bin/ # 启动脚本目录 ├── conf/ # 配置文件目录 ├── data/ # 数据目录(集群模式下主要用于本地缓存) ├── logs/ # 日志目录 └── target/ # 应用 jar 包三个节点的目录结构完全一致,区别只在于配置文件中的 IP 和端口设置。我建议在每台机器上用相同路径,这样后续维护和脚本编写都方便。
3.2 cluster.conf 集群配置详解
这是集群搭建最核心的一步。在conf目录下有一个cluster.conf.example文件,复制一份改名为cluster.conf,然后写入所有节点的地址。
cp conf/cluster.conf.example conf/cluster.conf vim conf/cluster.conf内容格式如下,每行一个节点,格式为IP:端口:
192.168.1.101:8848 192.168.1.102:8848 192.168.1.103:8848这里有几个容易出错的点需要特别注意。第一,必须使用 IP 地址,不能写 localhost 或 127.0.0.1,否则集群节点之间无法正确识别彼此。第二,端口写的是 HTTP 端口 8848,不是 gRPC 端口。第三,三个节点上的cluster.conf内容必须完全一致。
实操心得:如果你在云服务器上搭建,注意区分内网 IP 和公网 IP。
cluster.conf中应该填写节点之间可以互相通信的 IP,通常是内网 IP。如果填了公网 IP,不仅通信延迟高,还可能产生额外的流量费用。
3.3 application.properties 关键参数调整
接下来修改conf/application.properties,这是 Nacos 的核心配置文件。集群模式下需要修改的地方比单机模式多不少,我逐项说明。
首先是数据库配置,这是集群模式必须修改的:
# 数据库类型 spring.datasource.platform=mysql # 数据库实例数量 db.num=1 # 数据库连接地址 db.url.0=jdbc:mysql://192.168.1.100:3306/nacos_cluster?characterEncoding=utf8&connectTimeout=1000&socketTimeout=3000&autoReconnect=true&useUnicode=true&useSSL=false&serverTimezone=Asia/Shanghai # 数据库用户名和密码 db.user.0=nacos_user db.password.0=YourStrongPassword123然后是集群相关的配置:
# 集群模式标识 nacos.core.member.lookup.type=file # 服务端口 server.port=8848 # 管理端口(2.x 新增) management.server.port=8848还有一个非常重要的配置——JVM 参数。在bin/startup.sh中可以调整 JVM 内存参数。默认配置可能偏小,生产环境建议适当调大:
# 在 startup.sh 中找到 JVM 配置部分,调整为: JAVA_OPT="${JAVA_OPT} -Xms2g -Xmx2g -Xmn1g"注意:
-Xms和-Xmx建议设置为相同值,避免 JVM 频繁进行堆内存伸缩。-Xmn设置为堆内存的一半左右比较合适。如果节点内存充裕,可以适当调大。
3.4 启动集群并验证节点状态
配置完成后,就可以逐个启动节点了。Nacos 提供了启动脚本,使用-m cluster参数指定集群模式。
# 在每个节点上执行 cd /opt/nacos-cluster bash bin/startup.sh -m cluster启动完成后,查看日志确认节点是否正常:
# 查看启动日志 tail -f logs/start.out # 查看 Nacos 运行日志 tail -f logs/nacos.log如果一切正常,日志中会出现类似Nacos started successfully in cluster mode的输出。三个节点都启动后,打开浏览器访问任意一个节点的控制台:http://192.168.1.101:8848/nacos。默认用户名和密码都是nacos。
登录后进入集群管理 -> 节点列表,应该能看到三个节点,且每个节点的状态都是 UP。如果某个节点显示 DOWN 或者状态异常,就需要去查那个节点的日志排查问题。
实操心得:集群启动时,建议一个节点一个节点地启动,每启动一个确认状态正常后再启动下一个。三个节点同时启动有时会因为 Raft 选举竞争导致启动时间变长,虽然最终也能正常,但逐个启动更容易定位问题。
4. 集群验证与常见问题排查
4.1 功能验证:注册与配置同步测试
集群搭起来只是第一步,还得验证它是否真的能正常工作。我一般从两个维度验证:服务注册与发现和配置同步。
服务注册验证很简单,启动一个 Spring Boot 应用,配置 Nacos 地址为集群中任意一个节点,注册上去后,在控制台的服务列表中应该能看到这个服务。然后停掉这个 Nacos 节点,观察客户端是否能自动切换到其他节点继续工作。
配置同步验证更关键。通过节点 A 的控制台发布一个配置,然后分别通过节点 B 和节点 C 的控制台查询这个配置,如果能查到,说明配置同步正常。再进一步,直接停掉节点 A,通过节点 B 修改配置,然后重启节点 A,看它是否能同步到最新配置。
# 通过 OpenAPI 验证配置同步 # 在节点 A 发布配置 curl -X POST "http://192.168.1.101:8848/nacos/v1/cs/configs" \ -d "dataId=test-config&group=DEFAULT_GROUP&content=hello-nacos" # 在节点 B 查询配置 curl "http://192.168.1.102:8848/nacos/v1/cs/configs?dataId=test-config&group=DEFAULT_GROUP"如果节点 B 返回了hello-nacos,说明配置同步正常。
4.2 常见问题速查表
集群搭建过程中遇到的问题五花八门,我整理了一份常见问题速查表,覆盖了大部分场景:
| 问题现象 | 可能原因 | 排查方向 | 解决方案 |
|---|---|---|---|
| 节点启动后状态为 DOWN | 集群节点之间网络不通 | 检查 9849 和 7848 端口 | 放行防火墙端口 |
| 控制台无法访问 | 8848 端口未监听 | 查看启动日志是否有报错 | 检查 JDK 版本和端口占用 |
| 配置发布失败 | 数据库连接异常 | 检查 MySQL 连接配置 | 确认数据库地址、账号密码 |
| 节点频繁掉线 | 时钟不同步 | 检查各节点时间差 | 配置 NTP 时间同步 |
| 客户端连接超时 | gRPC 端口未放行 | 检查 9848 端口 | 放行 9848 端口 |
| 数据不一致 | Raft 选举异常 | 查看 raft 相关日志 | 确认节点数量为奇数 |
4.3 几个我踩过的坑
第一个坑是cluster.conf 中写了主机名而不是 IP。当时觉得用主机名更直观,结果节点之间解析不了对方的主机名,集群一直起不来。后来改成 IP 就正常了。所以再次强调,cluster.conf里老老实实写 IP。
第二个坑是MySQL 连接超时时间设置太短。默认配置中connectTimeout=1000和socketTimeout=3000在某些网络环境下偏短,导致 Nacos 频繁报数据库连接超时。后来把这两个值分别调整为3000和5000就稳定了。这个参数没有绝对标准,根据你的网络质量来调。
第三个坑是JVM 内存分配不合理。一开始给每个节点分配了 512MB 堆内存,结果服务实例稍微多一点就开始频繁 Full GC,节点响应变慢甚至假死。后来调整为 2GB 堆内存,问题消失。Nacos 作为基础组件,内存不能太抠。
提示:如果你在容器环境中部署 Nacos 集群,需要特别注意容器网络模式。使用 host 网络模式可以避免端口映射带来的 gRPC 通信问题,这也是官方推荐的方式。
5. 生产环境加固建议
5.1 开启鉴权与安全配置
默认情况下,Nacos 的控制台和 OpenAPI 是不需要认证的,这在生产环境是不可接受的。Nacos 支持开启鉴权,需要在application.properties中配置:
# 开启鉴权 nacos.core.auth.enabled=true # 鉴权系统类型 nacos.core.auth.system.type=nacos # 服务端身份识别密钥(自定义,长度建议 32 位以上) nacos.core.auth.server.identity.key=yourIdentityKey nacos.core.auth.server.identity.value=yourIdentityValue # JWT 令牌密钥(自定义,Base64 编码,长度建议 32 位以上) nacos.core.auth.plugin.nacos.token.secret.key=YourBase64EncodedSecretKeyHere开启鉴权后,客户端连接 Nacos 时需要配置用户名和密码。控制台登录也需要认证。这一步在生产环境是必须的,否则任何人都能修改你的配置、注册或下线服务,风险极大。
5.2 监控与告警配置
Nacos 集群上线后,监控是必不可少的。Nacos 本身提供了健康检查接口,可以配合监控系统使用:
# 健康检查接口 curl http://192.168.1.101:8848/nacos/actuator/health # 返回示例 {"status":"UP"}建议监控以下几个关键指标:节点存活状态、JVM 内存使用率、数据库连接池状态、配置变更频率、服务注册数量变化。如果使用 Prometheus + Grafana 的监控体系,Nacos 也支持暴露 metrics 数据,具体配置可以参考官方文档。
另外,Nacos 的日志需要定期清理。默认日志会一直累积,时间长了可能占满磁盘。可以在application.properties中配置日志保留天数,或者用定时任务清理旧日志。
5.3 数据备份与容灾策略
虽然 Nacos 集群本身有一定的容错能力,但数据库是单点。如果 MySQL 挂了,整个 Nacos 集群的配置管理功能都会受影响。所以生产环境建议对 MySQL 做主从复制或者使用云数据库的高可用版本。
配置数据的备份也很重要。Nacos 提供了配置导出功能,可以定期将配置导出为文件保存。另外,数据库层面也可以做定时备份,这样即使出现极端情况,也能快速恢复。
实操心得:我一般会在 Nacos 集群前面加一层负载均衡(比如 Nginx 或云负载均衡),客户端统一连接负载均衡地址,而不是直连某个节点。这样即使某个节点需要维护,客户端也不需要修改配置。负载均衡的健康检查要指向 Nacos 的健康检查接口,确保只转发到正常节点。
5.4 版本升级注意事项
Nacos 的版本迭代比较快,升级时需要注意兼容性。从 1.x 升级到 2.x 变化较大,尤其是端口和通信协议的变化,客户端也需要同步升级。升级集群时,建议采用滚动升级的方式:先停一个节点,升级完成后启动并确认状态正常,再升级下一个节点。这样在整个升级过程中,集群始终有可用节点,不会影响业务。
升级前一定要备份数据库和配置文件。虽然 Nacos 的升级脚本通常会自动处理表结构变更,但手动备份一份总是没错的。我就遇到过升级过程中数据库表结构变更失败导致节点起不来的情况,幸好有备份,回滚很快。
集群搭建这件事,说难不难,说简单也不简单。核心就是把网络、数据库、配置文件这三块搞清楚,剩下的就是细心和耐心。我见过太多团队因为 cluster.conf 写错一个 IP 或者防火墙少开一个端口,折腾了大半天。希望这篇内容能帮你少走一些弯路。如果你在搭建过程中遇到什么奇怪的问题,欢迎一起交流。