概述单机 Nacos 是整个微服务体系里唯一一个挂了就全挂的组件——服务发现和配置下发都走它。这篇把 Nacos 从单机改成三节点集群三个 Nacos 实例 一个共享 MySQL Nginx 统一入口每一步都给到可复制的命令与配置顺带说清cluster.conf填127.0.0.1这个最经典的坑。纲要单机 Nacos 的致命点注册中心是全站单点集群结构3 个 Nacos 节点 1 个共享 MySQL Nginx 负载均衡为什么必须把内嵌 Derby 换成 MySQL搭建七步初始化 MySQL建库 导入nacos-mysql.sql配置conf/application.properties接 MySQL配置conf/cluster.conf列节点复制三份、分别改端口 8845 / 8846 / 8847逐节点启动集群模式不加-m standaloneNginxupstreamlocation /nacos验证控制台「集群管理 → 节点列表」客户端怎么连集群server-addr写 Nginx 地址还是多地址目录结构 / 容量规划 / 实战坑单机 Nacos 到底危险在哪我们前面几节用的都是单节点 Nacos自己跑 demo 没问题生产上用就是给自己埋雷。原因不在于怕挂而在于挂的是谁。一个普通微服务挂掉受影响的是它自己那条链路Nacos 挂掉受影响的是全站所有服务拉不到实例列表新起的实例注册不上配置改动下发不下去。它是注册中心 配置中心处在调用链的源头一挂就是级联失败。这个单点比任何一个业务服务都致命。集群要解决的就是这个单点。三个节点里挂一个另外两个照常服务注册与配置能力不中断。集群内部的数据一致性由Raft协议保证写请求要拿到多数派的确认才算成功。这带来两个直接结论3 个节点能容忍 1 个挂掉剩 2 个仍是多数派5 个节点能容忍 2 个——所以生产至少 3 节点2 节点反而不如 1 节点没有多数派可言宕一个就写不进去部署节点数尽量用奇数偶数节点不会提升容错能力只会多占资源集群结构官方给的集群图思路很简单前面一个负载均衡器后面挂多个 Nacos 节点客户端只访问负载均衡器。负载均衡器我们用 Nginx因为它本来就干反向代理和负载均衡。upstream nacos-clusteruser-serviceNginx反向代理 / 负载均衡监听 80order-servicegatewaynacos1192.168.150.101:8845nacos2192.168.150.101:8846nacos3192.168.150.101:8847MySQLnacos 库共享存储三个节点的规划IP 按你自己的机器改端口不冲突即可节点IPport说明nacos1192.168.150.1018845从同一份解压目录复制出来nacos2192.168.150.1018846同上nacos3192.168.150.1018847同上本机演示时三个节点 IP 相同、端口不同生产上应该把它们放到三台不同机器顺手做好容灾隔离。数据共享这一环是让三个 Nacos 都去连同一个 MySQL 库谁写进去的配置另外两个查的时候都能看到数据自然就一致了。为什么必须换成 MySQL不能用内嵌 DerbyNacos 单机默认把数据存在内嵌 Derby 里。Derby 是每个 Nacos 进程各自一份、跟着进程走的本地文件库。三个节点就是三个独立的 Derby各存各的A 节点发布的配置 B 节点根本看不到——数据都不共享集群无从谈起。所以集群模式的第一件事就是把存储切到外部数据库。对比一下维度内嵌 DerbyMySQL外部存储数据存放位置每个 Nacos 进程内部独立数据库服务多节点是否共享不共享各存各的共享同一份数据是否支持集群不支持支持生产可用性仅单机调试官方推荐可做主从高可用是否需要额外部署不需要需要部署并初始化表结构官方推荐的最佳实践是带主从的高可用数据库集群。下面为了讲清流程先用单点 MySQL 演示。搭建七步准备 MySQL建库并导入初始化脚本Nacos 1.4.1 的安装包里已经带了建表脚本conf/nacos-mysql.sql里面是配置表、历史表、容量表以及鉴权用的users/roles/permissions。先建库再整份导入。-- 1. 建库字符集用 utf8CREATEDATABASEnacosDEFAULTCHARACTERSETutf8COLLATEutf8_general_ci;# 2. 导入安装包自带的建表脚本路径按你的解压位置改mysql-uroot-p123-h127.0.0.1-P3306nacos/opt/nacos/conf/nacos-mysql.sql-- 3. 验证应该能看到这些表USEnacos;SHOWTABLES;-- config_info / config_info_aggr / config_info_beta / config_info_tag-- config_tags_relation / group_capacity / his_config_info / tenant_capacity-- tenant_info / users / roles / permissions脚本里还带了一个可直接登录控制台的默认管理员账号-- 鉴权相关表与初始账号nacos-mysql.sql 尾部已包含CREATETABLEusers(usernamevarchar(50)NOTNULLPRIMARYKEY,passwordvarchar(500)NOTNULL,enabledbooleanNOTNULL);INSERTINTOusers(username,password,enabled)VALUES(nacos,$2a$10$EuWPZHzz32dJN7jexM34MOeYirDdFAZm2kuWj7VEOJhhZkDrxfvUu,TRUE);INSERTINTOroles(username,role)VALUES(nacos,ROLE_ADMIN);-- 默认账号 nacos / nacos导入失败最常见的两个原因库没建成或字符集不是 utf8脚本跑到longtext字段报错另一个是客户端连接时serverTimezone没配datetime字段写入报The server time zone value ... is unrecognized。配置 application.properties让 Nacos 连上 MySQL进入 Nacos 的conf目录改application.properties。要动的就这几行注意把行首的#注释删掉——讲义里专门提醒过很多人改完启动还是连 Derby就是因为这几行还在注释状态。### 数据源平台指定用 mysql spring.datasource.platformmysql ### MySQL 实例数量单点写 1 db.num1 ### 连接 URL库名 nacos字符集 utf8关掉 SSL指定时区 db.url.0jdbc:mysql://127.0.0.1:3306/nacos?characterEncodingutf8connectTimeout1000socketTimeout3000autoReconnecttrueuseUnicodetrueuseSSLfalseserverTimezoneUTC ### 账号密码按实际情况改 db.user.0root db.password.0123db.num是这个集群里有几台 MySQL单点写 1。如果配了多台URL 就按db.url.0、db.url.1… 依次往下排账号密码同理。配置 cluster.conf列出所有节点conf目录里给的是模板文件cluster.conf.example直接去掉.example后缀重命名为cluster.conf。这个文件名和格式都不能错写错了 Nacos 会认为你还在单机模式。192.168.150.101:8845 192.168.150.101:8846 192.168.150.101:8847一行一个ip:port把集群里所有节点都列进去不要加逗号、不要加多余空格。改完 Nacos 才会按集群模式去组网。这里有个最容易踩的坑IP 必须写其他节点能访问到的真实 IP。写localhost或127.0.0.1本节点自己连得上但节点之间互相访问时这个地址没有意义集群组不起来控制台节点列表里每个节点都是DOWN或者根本不出现。不确定自己机器 IP 的话先单机起一个 Nacos进控制台看「节点列表」里显示的 IP照着填就行。复制三份分别改端口配置改好一份之后把整个 Nacos 目录复制出三份分别命名nacos1、nacos2、nacos3然后各改各的server.port。nacos1/conf/application.properties - server.port8845 nacos2/conf/application.properties - server.port8846 nacos3/conf/application.properties - server.port8847对应的配置内容# nacos1 server.port8845# nacos2 server.port8846# nacos3 server.port8847三份目录里的application.properties除了server.port不同数据库配置和cluster.conf都是一样的。复制实例后忘改端口是启动时报Port 8848 was already in use的直接原因。三份目录的最终结构nacos-cluster/ ├── nacos1/ │ ├── bin/ │ │ ├── startup.sh # Linux / macOS 启动脚本 │ │ ├── startup.cmd # Windows 启动脚本 │ │ ├── shutdown.sh │ │ └── shutdown.cmd │ ├── conf/ │ │ ├── application.properties # server.port8845含 MySQL 配置 │ │ ├── cluster.conf # 三节点 ip:port 列表 │ │ ├── nacos-mysql.sql # 建表脚本 │ │ └── nacos-logback.xml │ └── target/ ├── nacos2/ │ └── conf/application.properties # server.port8846 └── nacos3/ └── conf/application.properties # server.port8847逐个启动集群模式不加 standalone进到每个节点的bin目录执行启动脚本。关键差异在这里单机启动时用的是sh startup.sh -m standalone集群模式下要去掉-m standalone脚本默认就是集群启动。# nacos1cd/opt/nacos-cluster/nacos1/binshstartup.sh# nacos2cd/opt/nacos-cluster/nacos2/binshstartup.sh# nacos3cd/opt/nacos-cluster/nacos3/binshstartup.shWindows 下对应执行startup.cmd。# 确认三个进程都在ps-ef|grepnacos|grep-vgrep坑就在这个参数上集群模式下带着-m standalone起你会得到三个互不相干的单机 Nacos各自用各自的 Derby控制台节点列表里只有自己一个节点看起来起来了其实压根没成集群。日志里可以确认模式# 看启动日志集群模式下会打印 Nacos started successfully in cluster modetail-f/opt/nacos-cluster/nacos1/logs/start.outNginx 反向代理客户端不该关心后面有几个 Nacos、都是什么端口统一从一个入口进。在nginx/conf/nginx.conf的http { }块里加上upstream和后端serverhttp { # 集群内三个 Nacos 节点Nginx 会在这三个之间做负载均衡 upstream nacos-cluster { server 192.168.150.101:8845; server 192.168.150.101:8846; server 192.168.150.101:8847; } server { listen 80; server_name localhost; # Nacos 默认上下文路径就是 /nacos原样透传 location /nacos { proxy_pass http://nacos-cluster; } } }启动 Nginxcd/opt/nginx/sbin ./nginx# 启动./nginx-sreload# 改完配置平滑重载upstream的名字和proxy_pass里的名字要一致location后面的路径是/nacos不是/。配好之后访问时不再带 8848 端口直接走 80。验证集群是否组建成功浏览器访问 Nginx 的地址本机就是http://localhost/nacos进控制台「集群管理 → 节点列表」三个节点应该都在状态正常节点列表 -------------------------------------------------------------------------------- 节点地址 状态 权重 最后心跳时间 192.168.150.101:8845 UP 1 2021-08-30 17:02:29 192.168.150.101:8846 UP 1 2021-08-30 17:02:29 192.168.150.101:8847 UP 1 2021-08-30 17:02:30 --------------------------------------------------------------------------------三个节点都UP集群就成了。再顺手验一把持久化在控制台「配置管理」新建一条配置并发布然后去数据库里查配置内容已经落进 MySQL 的表里说明共享存储生效。SELECTdata_id,group_id,contentFROMconfig_info;如果节点列表里节点是DOWN按顺序查三件事cluster.conf里的 IP 是不是真实可达 IP、三个节点的server.port是不是真的改开了、三个节点是不是都连到了同一个 MySQL。客户端怎么连集群搭建完最容易漏掉的一步微服务里的 Nacos 地址要改。搭建前配置里写的是server-addr: localhost:8848单节点现在前面挡了一层 Nginx要指向 Nginx。# 写法一只写 Nginx 地址推荐集群规模变化时客户端不用动spring:cloud:nacos:server-addr:192.168.150.101:80# 指向 Nginx由 Nginx 转发到后端节点# 写法二直连多个节点逗号分隔不经过 Nginxspring:cloud:nacos:server-addr:192.168.150.101:8845,192.168.150.101:8846,192.168.150.101:8847两种写法对比对比项写 Nginx 地址直接写多节点地址客户端配置复杂度一个地址最简单要维护完整节点列表节点增删时只改 Nginx客户端不动每个服务都得改配置负载均衡位置Nginx 统一做客户端自己挑节点排查问题多一层 Nginx链路稍长直连节点排查更直接适用场景生产推荐节点会扩容临时验证、无 Nginx 环境生产环境建议用写法一并且给 Nginx 挂一个域名。这样以后要做 Nacos 服务器迁移只改域名解析所有客户端配置一行都不用动。改完重启微服务进 Nacos 控制台「服务管理 → 服务列表」两个实例都注册上来说明客户端已经正确连上集群。容量与优化按重要性排一下真要到生产需要考虑的点优化项做法原因节点数用奇数至少 3 个3 或 5 个节点Raft 写需要多数派3 节点可容忍 1 个挂MySQL 做主从或高可用主从复制 故障切换换掉 Derby 后MySQL 成了新的单点节点分散部署三个节点放三台机器单机部署三节点机器一挂全挂容灾无意义开启鉴权配置nacos.core.auth.enabledtrue集群暴露后默认无鉴权配置和注册接口谁都能调调整 JVM 参数改bin/startup.sh的JAVA_OPT默认堆偏小节点多了容易 OOM日志与数据目录规划单独挂盘配日志清理日志和本地数据写爆系统盘会连带影响服务实战坑清单现象原因处理节点列表全DOWN或只有自己cluster.conf里写了localhost/127.0.0.1改成其他节点能访问的真实 IP启动报端口被占用复制实例后忘了改server.port三个节点分别改成 8845/8846/8847启动报建表或字段相关错误MySQL 没建库或没导入nacos-mysql.sql建库nacos整份导入建表脚本三个节点各自为政只有本节点集群模式误加了-m standalone去掉该参数脚本默认集群启动Raft 选举异常、节点频繁上下线三台机器时间不同步用 NTP 做时间同步各节点时差别超过几百毫秒Nacos 2.x 升级后 9848/9849 连不上2.x 新增 gRPC 端口Nginx 只代理了 8848额外转发 9848/9849本文的 1.4.1 无此问题关于最后一条多说一句Nacos 1.4.1 只有 HTTP 端口8845/8846/8847Nginx 配一个upstream就够。Nacos 2.x 引入了 gRPC 长连接客户端除了主端口还会连主端口1000、主端口1001也就是 8848 对应 9848/9849。如果按本文的配置直接套到 2.x 上控制台能打开但客户端注册会连不上——升级版本时这块配置要跟着加。命令与配置速览项目值 / 命令建库CREATE DATABASE nacos DEFAULT CHARACTER SET utf8;导入建表脚本mysql -uroot -p123 nacos conf/nacos-mysql.sql数据源开关spring.datasource.platformmysqlMySQL 数量db.num1集群节点列表conf/cluster.conf一行一个ip:port集群端口nacos18845、nacos28846、nacos38847启动集群sh startup.sh不加-m standalone关闭sh shutdown.shNginx 入口location /nacos { proxy_pass http://nacos-cluster; }控制台访问http://nginx地址/nacos默认账号nacos/nacos官方文档Nacos 集群部署说明官方Nacos Release 下载页Nacos 部署手册1.4.1总结集群搭建本身不复杂五步走完初始化数据库、下载解压、改集群与数据库配置、多节点启动、Nginx 反向代理。真正决定成不成的是三个细节——cluster.conf里的 IP 必须是真实可达 IP集群启动不能带-m standalone存储必须从 Derby 换成共享的 MySQL。搭建前客户端连的是单个节点地址搭建后要改成 Nginx 地址或多节点地址这一步很多教程会漏掉改完才算真正切到集群。
阅读完成 · 觉得有帮助?