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-node1Leader动态选举注册中心 配置中心nacos-node2Follower注册中心 配置中心nacos-node3Follower注册中心 配置中心硬件方面每个 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 默认使用以下端口8848HTTP 端口用于控制台访问和 OpenAPI9848gRPC 客户端通信端口供 Nacos 客户端连接使用9849gRPC 服务端通信端口用于集群节点之间的数据同步7848Raft 通信端口用于集群选举和数据一致性这四个端口缺一不可。很多人在搭建集群后发现节点之间无法通信八成是防火墙没放行 9849 和 7848 端口。我个人的习惯是在搭建之前就把这些端口的防火墙规则全部配好省得后面排查半天。# 以 firewalld 为例放行 Nacos 所需端口 sudo firewall-cmd --permanent --add-port8848/tcp sudo firewall-cmd --permanent --add-port9848/tcp sudo firewall-cmd --permanent --add-port9849/tcp sudo firewall-cmd --permanent --add-port7848/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.platformmysql # 数据库实例数量 db.num1 # 数据库连接地址 db.url.0jdbc:mysql://192.168.1.100:3306/nacos_cluster?characterEncodingutf8connectTimeout1000socketTimeout3000autoReconnecttrueuseUnicodetrueuseSSLfalseserverTimezoneAsia/Shanghai # 数据库用户名和密码 db.user.0nacos_user db.password.0YourStrongPassword123然后是集群相关的配置# 集群模式标识 nacos.core.member.lookup.typefile # 服务端口 server.port8848 # 管理端口2.x 新增 management.server.port8848还有一个非常重要的配置——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 dataIdtest-configgroupDEFAULT_GROUPcontenthello-nacos # 在节点 B 查询配置 curl http://192.168.1.102:8848/nacos/v1/cs/configs?dataIdtest-configgroupDEFAULT_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 连接超时时间设置太短。默认配置中connectTimeout1000和socketTimeout3000在某些网络环境下偏短导致 Nacos 频繁报数据库连接超时。后来把这两个值分别调整为3000和5000就稳定了。这个参数没有绝对标准根据你的网络质量来调。第三个坑是JVM 内存分配不合理。一开始给每个节点分配了 512MB 堆内存结果服务实例稍微多一点就开始频繁 Full GC节点响应变慢甚至假死。后来调整为 2GB 堆内存问题消失。Nacos 作为基础组件内存不能太抠。提示如果你在容器环境中部署 Nacos 集群需要特别注意容器网络模式。使用 host 网络模式可以避免端口映射带来的 gRPC 通信问题这也是官方推荐的方式。5. 生产环境加固建议5.1 开启鉴权与安全配置默认情况下Nacos 的控制台和 OpenAPI 是不需要认证的这在生产环境是不可接受的。Nacos 支持开启鉴权需要在application.properties中配置# 开启鉴权 nacos.core.auth.enabledtrue # 鉴权系统类型 nacos.core.auth.system.typenacos # 服务端身份识别密钥自定义长度建议 32 位以上 nacos.core.auth.server.identity.keyyourIdentityKey nacos.core.auth.server.identity.valueyourIdentityValue # JWT 令牌密钥自定义Base64 编码长度建议 32 位以上 nacos.core.auth.plugin.nacos.token.secret.keyYourBase64EncodedSecretKeyHere开启鉴权后客户端连接 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 或者防火墙少开一个端口折腾了大半天。希望这篇内容能帮你少走一些弯路。如果你在搭建过程中遇到什么奇怪的问题欢迎一起交流。