3台机器、40分钟、零停机:Nacos生产集群搭建全纪录
3台机器、40分钟、零停机:Nacos生产集群搭建全纪录
生产环境用单机?同事说"挂了算你的"
"Nacos 挂了,所有服务注册发现都停了。"凌晨两点,运维的电话把我叫醒。
查了半天发现:生产环境跑的是 standalone 模式,一台机器。那台机器回收磁盘空间时把 Nacos 进程误杀了。
第二天我花了 40 分钟搭了一套 3 节点集群。从那以后,任何一台节点挂了,另外两台自动接管,客户端无感知。
这篇文章就是那次搭建的完整记录——从 MySQL 主从到 cluster.conf 到 Nginx 负载均衡,每一步都附配置文件和验证命令。
为什么必须集群?三个真实场景
单机模式三大死穴:机器宕机全挂、OOM 中断服务、Derby 数据说没就没。集群用 3 台机器 + MySQL 把这三个问题全解决了。
第一步:环境总览
拓扑规划
| 角色 | IP | 端口 | 说明 |
|---|---|---|---|
| Nacos Node 1 | 192.168.1.101 | 8848 / 9848 / 9849 | 集群节点1 |
| Nacos Node 2 | 192.168.1.102 | 8848 / 9848 / 9849 | 集群节点2 |
| Nacos Node 3 | 192.168.1.103 | 8848 / 9848 / 9849 | 集群节点3 |
| MySQL 主库 | 192.168.1.100 | 3306 | 集群共享数据源 |
| Nginx | 192.168.1.200 | 80/443 | 统一入口 + 负载均衡 |
客户端连 Nginx,Nginx 分发到任意节点。三个节点共享同一个 MySQL。节点之间通过 9849 端口做集群通信。
🔗 集群部署之前,先确保单机能跑起来。还没搭过的看这篇:第一次搭Nacos踩了5个坑——单机部署从零开始
第二步:MySQL 初始化
-- 1. 创建数据库CREATEDATABASEIFNOTEXISTSnacos_configDEFAULTCHARACTERSETutf8mb4DEFAULTCOLLATEutf8mb4_general_ci;-- 2. 创建用户(生产环境不要用 root)CREATEUSER'nacos'@'%'IDENTIFIEDBY'Nacos@2024!';GRANTALLPRIVILEGESONnacos_config.*TO'nacos'@'%';FLUSHPRIVILEGES;-- 3. 导入表结构(2.3.2 版本)-- 表文件在 nacos/conf/mysql-schema.sql 里-- 或者直接启动一次 Nacos standalone 连 MySQL,会自动建表坑1:MySQL 版本兼容性。Nacos 2.x 需要在 MySQL 5.7+ 或 8.0+。MySQL 5.6 的utf8mb4和timestamp行为不同,会导致建表失败。
第三步:配置 cluster.conf
这是集群模式最核心的文件。每个节点都要配,内容完全一样:
# nacos/conf/cluster.conf # 格式:IP:端口(集群通信端口,不是 8848) 192.168.1.101:9849 192.168.1.102:9849 192.168.1.103:9849坑2:别写 8848。cluster.conf里写的是集群节点间通信端口 9849,不是 HTTP 端口 8848。写错了集群成员列表是空的。
坑3:不能写 127.0.0.1。集群节点之间需要真实 IP 通信。127.0.0.1 只能本机用,其他节点连不上。
第四步:修改 application.properties
每台机器上的conf/application.properties做以下修改(三台完全一样):
# ===== 1. 禁用内置 Derby,切换到 MySQL ===== spring.sql.init.platform=mysql db.num=1 db.url.0=jdbc:mysql://192.168.1.100:3306/nacos_config?useSSL=false&serverTimezone=Asia/Shanghai&characterEncoding=utf8&connectTimeout=5000&socketTimeout=10000 db.user.0=nacos db.password.0=Nacos@2024! # ===== 2. 集群模式(不写 standalone) ===== # 只要 cluster.conf 存在且有内容,自动进入集群模式 # ===== 3. 调大 JVM 内存(生产建议) ===== # 这个在 bin/startup.sh 里改,不动 properties # -Xms2g -Xmx2g -Xmn1g三个节点这文件完全一样,复制粘贴即可。
第五步:逐节点启动
# Node 1(192.168.1.101)cd/opt/nacos/bin ./startup.sh# 不传 -m standalone,默认集群模式# 等 Node 1 启动成功后(约 30~60 秒)# Node 2(192.168.1.102)cd/opt/nacos/bin ./startup.sh# 再等 30~60 秒,最后启动 Node 3(192.168.1.103)cd/opt/nacos/bin ./startup.sh坑4:不要同时启动三个节点。启动顺序很重要。先启动的节点会发起选举。同时启动会导致脑裂——两个节点都认为自己是 Leader。
启动顺序:先启 Node1(自举为 Leader),再启 Node2 和 Node3(发现 Leader 已存在,以 Follower 身份加入)。
第六步:验证集群状态
检查每个节点是否启动成功
# 看启动日志tail-f/opt/nacos/logs/start.out# 成功的标志:# INFO Nacos started successfully in cluster mode.# INFO The server is ready to receive requests.检查集群成员
# 查任意节点的集群信息curl-XGET"http://192.168.1.101:8848/nacos/v1/core/cluster/nodes"# 返回示例:# [# {"ip":"192.168.1.101","port":8848,"state":"UP","extendInfo":{"raftPort":9849}},# {"ip":"192.168.1.102","port":8848,"state":"UP","extendInfo":{"raftPort":9849}},# {"ip":"192.168.1.103","port":8848,"state":"UP","extendInfo":{"raftPort":9849}}# ]三个节点state都是UP,集群正常。
验证数据一致性
# 在 Node1 上注册一个服务curl-XPOST"http://192.168.1.101:8848/nacos/v1/ns/instance"\-d"serviceName=test-service&ip=10.0.0.1&port=8080"# 在 Node3 上查这个服务curl"http://192.168.1.103:8848/nacos/v1/ns/instance/list?serviceName=test-service"Node3 返回了 Node1 注册的服务,说明集群数据同步正常。
第七步:Nginx 负载均衡
客户端不应该直连某一个 Nacos 节点——那个节点挂了所有客户端都得切地址。用 Nginx 做统一入口:
# /etc/nginx/conf.d/nacos-cluster.conf upstream nacos_cluster { # 最少连接数策略 least_conn; server 192.168.1.101:8848 weight=1 max_fails=3 fail_timeout=30s; server 192.168.1.102:8848 weight=1 max_fails=3 fail_timeout=30s; server 192.168.1.103:8848 weight=1 max_fails=3 fail_timeout=30s; # 长连接优化 keepalive 32; keepalive_timeout 60s; } server { listen 80; server_name nacos.your-domain.com; # 控制台 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; } # API 请求 location /nacos/v1 { proxy_pass http://nacos_cluster; proxy_set_header Host $host; proxy_http_version 1.1; proxy_set_header Connection ""; } }客户端改一下配置:
spring:cloud:nacos:discovery:server-addr:nacos.your-domain.com:80# 不再是写死 192.168.1.101:8848 了第八步:故障演练——确认高可用真的有效
# 关闭 Node2ssh192.168.1.102"/opt/nacos/bin/shutdown.sh"# 立即查 Node1 的集群状态curl"http://192.168.1.101:8848/nacos/v1/core/cluster/nodes"# 返回:Node2 状态变成 DOWN,Node1 和 Node3 还是 UP# 客户端仍在正常注册发现服务# Node2 上的流量自动切到 Node1 和 Node3集群模式下任意一个节点挂掉,服务不中断。只有三个节点全挂才会不可用。
Docker Compose 一键部署(测试环境用)
# docker-compose.ymlversion:'3.8'services:mysql:image:mysql:8.0container_name:nacos-mysqlenvironment:MYSQL_ROOT_PASSWORD:root123MYSQL_DATABASE:nacos_configMYSQL_USER:nacosMYSQL_PASSWORD:Nacos@2024!ports:-"3306:3306"volumes:-./mysql-init.sql:/docker-entrypoint-initdb.d/init.sqlcommand:--character-set-server=utf8mb4--collation-server=utf8mb4_general_cinacos1:image:nacos/nacos-server:v2.3.2container_name:nacos-node1environment:-MODE=cluster-NACOS_SERVERS=nacos1:9849 nacos2:9849 nacos3:9849-SPRING_DATASOURCE_PLATFORM=mysql-MYSQL_SERVICE_HOST=mysql-MYSQL_SERVICE_PORT=3306-MYSQL_SERVICE_DB_NAME=nacos_config-MYSQL_SERVICE_USER=nacos-MYSQL_SERVICE_PASSWORD=Nacos@2024!ports:-"8848:8848"-"9848:9848"-"9849:9849"depends_on:-mysqlnacos2:image:nacos/nacos-server:v2.3.2container_name:nacos-node2environment:-MODE=cluster-NACOS_SERVERS=nacos1:9849 nacos2:9849 nacos3:9849-SPRING_DATASOURCE_PLATFORM=mysql-MYSQL_SERVICE_HOST=mysql-MYSQL_SERVICE_PORT=3306-MYSQL_SERVICE_DB_NAME=nacos_config-MYSQL_SERVICE_USER=nacos-MYSQL_SERVICE_PASSWORD=Nacos@2024!ports:-"8849:8848"-"9849:9848"-"9859:9849"# 端口映射避免冲突depends_on:-nacos1nacos3:image:nacos/nacos-server:v2.3.2container_name:nacos-node3environment:-MODE=cluster-NACOS_SERVERS=nacos1:9849 nacos2:9849 nacos3:9849-SPRING_DATASOURCE_PLATFORM=mysql-MYSQL_SERVICE_HOST=mysql-MYSQL_SERVICE_PORT=3306-MYSQL_SERVICE_DB_NAME=nacos_config-MYSQL_SERVICE_USER=nacos-MYSQL_SERVICE_PASSWORD=Nacos@2024!ports:-"8850:8848"-"9850:9848"-"9860:9849"depends_on:-nacos2# 一键启动docker-composeup-d# 等所有容器就绪后检查docker-composeps# 所有 nacos-node* 状态应该是 healthy常见集群问题速查
| 现象 | 原因 | 解决 |
|---|---|---|
| 每个节点只能看到自己 | cluster.conf 里写了 127.0.0.1 | 改成真实 IP |
| 访问任意节点都卡死 | MySQL 连不上或表没建 | 检查 MySQL 地址和nacos_config数据库 |
| 启动后反复选举 | 三个节点同时启动导致脑裂 | 关闭所有节点,间隔 30 秒逐个启动 |
9849 Address already in use | 上一轮进程没杀掉 | kill -9残留进程 |
| 注册的服务一部分节点看不到 | 集群节点间网络不通 | 三个节点互相 telnet 9849 端口 |
总结
三节点集群搭建的核心:
- MySQL 共享存储:三个节点连同一个 MySQL,数据天然一致。
- cluster.conf:写三个节点的真实 IP + 9849 端口,不能写 127.0.0.1。
- 逐个启动:间隔 30 秒,避免同时启动导致脑裂。
- Nginx 统一入口:客户端连 Nginx,不直连任何一台节点。
- 故障验证:关一个节点,确认另两个正常、客户端无感知。
从单机到集群,本质上加了三个东西:MySQL 共享存储 + cluster.conf 节点列表 + Nginx 负载均衡。其他配置跟单机一模一样。
你们生产环境 Nacos 怎么搭的?评论区留个数字:1=单机跑着没出事(心大) 2=3节点集群+MySQL 3=k8s部署 4=还没上生产。顺便说说你遇到过最离谱的 Nacos 故障是什么。
