前阵子帮一个项目组搭微服务基础环境,花了大半天折腾 Nacos,中间踩了一堆坑,从版本选型到数据库切换,再到配置动态刷新,每一步都有不少细节值得记下来。这篇就把从零开始下载、安装、配置 Nacos 的完整过程写出来,顺便把那些不翻文档根本发现不了的坑也一并说了。无论你是第一次接触 Nacos 的新手,还是已经跑过服务但想理清配置中心、命名空间这些概念的开发者,这篇应该都能帮上忙。
Nacos 现在基本是 Java 微服务圈子里的标配了,它同时承担服务注册发现(注册中心)和动态配置管理(配置中心)两个职责,可以替换掉传统的 Eureka 加 Spring Cloud Config 组合。不过正因为功能多,安装配置环节的决问题也多,尤其是 Nacos 2.x 版本换了通信协议之后,很多老教程已经不管用了。下面我按自己实际操作的顺序来拆解整个流程。
1. 整体设计与思路拆解:先搞清楚 Nacos 能干什么,再决定怎么装
1.1 注册中心与配置中心,一个组件两件事
Nacos 全称是 Dynamic Naming and Configuration Service,阿里开源的一个中间件。它核心解决两件事:一是服务注册与发现,也就是各个微服务启动后把自己的 IP 和端口上报到一个中心,其他服务调用时从这个中心拿到地址列表;二是动态配置管理,把配置从应用代码里抽离出来集中管理,修改配置后不需要重启服务就能生效。
我见过不少新手一上来就急着下载安装,结果装完打开控制台发现功能很多,根本不知道从哪入手。实际上你要理解的第一件事是:Nacos 的使用分客户端和服务端两层。本篇讲的安装配置属于服务端,也就是你要跑起来的那个 Nacos Server;而你的微服务项目是客户端,需要通过依赖引入 Nacos Discovery 和 Nacos Config 来连接服务端。搞清楚这一层,后面无论你怎么折腾,思路都不会乱。
1.2 明确你的部署场景,单机还是集群
安装 Nacos 之前,先想清楚你的场景。本地开发调试,单机模式就够了,默认使用内置数据库;生产环境至少得三节点做集群,并且必须切换外部数据库。为什么?因为 Nacos 单机模式用的是内嵌的 Derby 数据库,一旦节点挂了数据就丢,而且 Derby 不支持跨实例共享,集群模式下每个节点的数据各存各的,根本无法保持一致。所以生产用 MySQL 是硬性要求,不然后面有你哭的。
另外 Nacos 2.x 和 1.x 的安装配置差异很大,最大的变化是通信协议从 HTTP 长轮询改成了 gRPC,文档里如果没提这个差异,你照着 1.x 的教程很容易栽跟头。
2. 下载前的准备与版本选型,这一步最容易被忽视
2.1 环境依赖:JDK 和 Maven 不是可选项
很多教程会告诉你 Nacos 只需要 JDK 就能跑,实际上仅就启动服务器来说,装个 JDK 8 以上确实够了。但如果你要给自己的微服务项目引入 Nacos 依赖,Maven 或 Gradle 就必不可少。我个人建议本地环境统一装 JDK 8 或 11、Maven 3.6 以上,这两样最好在装 Nacos 之前就配好,省得后面一边排查环境变量一边找问题,那种感觉特别酸爽。
JDK 安装要注意的是环境变量配置完一定要验证。Windows 下很多人配完之后java -version能输出版本号,但javac -version报错,这就是 PATH 里没有配好,或者装的是 JRE 而不是完整 JDK。Maven 也类似,配好之后mvn -v验证一下,顺便看看它用的 JDK 版本。这个步骤虽然基础,但我真的见过因为 Maven 指向了旧 JDK 导致 Nacos 源码编译失败的案例,所以先花两分钟检查一下。
2.2 版本选择:2.2.x 是当前最稳的选择
Nacos 版本选择真的很关键。目前主流稳定版是 2.2.x 和 2.3.x,我推荐新项目直接用 2.2.3 或更新的 2.3.x,这两个版本对 MySQL 8、gRPC 通信、鉴权配置都支持得比较完善。很多老教程还在用 1.4.x,如果你照着做,项目里 Spring Cloud Alibaba 版本稍高一点就会遇到兼容性问题,因为 2.x 的服务端和 1.x 的客户端在某些接口上是不兼容的。
从 GitHub 的 Releases 页面下载时,注意看清楚两个包的区别:nacos-server-2.2.3.zip是编译好的二进制包,解压就能用;nacos-2.2.3-source.zip是源码包,需要自己 Maven 编译。绝大多数情况下直接下载二进制包就行,自己编译纯属浪费时间,除非你要改源码。
提示:GitHub 下载慢的话,可以用阿里云的镜像仓库加速,或者直接在 Nacos 官网下载页找对应的国内链接。
2.3 下载源与完整性校验
下载 Nacos 时建议直接从 GitHub 官方 Releases 或官网下载,不要随便在第三方博客的网盘链接里下载。开源软件在传播过程中被人动过手脚的事情不是没有,中间件是基础设施,被植入后门是内网传输层面的大忌。下载完成后,Windows 下可以用 PowerShell 的Get-FileHash命令计算 SHA256 哈希,和官方给出的校验值比对;Linux 下直接用sha256sum。这一步看起来多余,但对生产环境安装属于必须操作,本地开发随意就行。
3. 单机模式安装实操:Windows、Linux、Mac 全走一遍
3.1 Windows 解压即用,但这些细节不能省
Windows 下安装 Nacos 是真的简单,但细节决定成败。首先,解压路径千万别带中文和空格,比如C:\Program Files\nacos这种路径容易引起脚本执行问题,最好直接放D:\nacos这种干净的路径下。解压完成后,进入bin目录,直接双击startup.cmd不行吗?可以的,但默认是集群模式,你本地只有一个节点,它会因为找不到集群节点配置而启动失败,或者启动后控制台各种诡异报错。
正确的启动方式是在bin目录下打开命令行(CMD 或 PowerShell),执行:
startup.cmd -m standalone-m standalone就是明确指定单机模式。启动后如果看到Nacos started successfully就说明成功了。然后浏览器访问http://localhost:8848/nacos,默认账号密码都是nacos/nacos,第一次登录系统会提示你修改密码,建议直接改掉。
启动失败想排查问题时,Windows 下日志文件在logs目录下的start.out里,千万别只看控制台窗口的输出,那个窗口一旦关闭日志就不全了。我遇到过一次窗口提示启动成功,但控制台页面死活打不开,后来看start.out才发现数据库连接池初始化失败了,这种问题不查日志根本定位不了。
3.2 Linux 环境安装:CentOS Stream 9 的完整步骤
Linux 下的流程稍复杂一些,但核心就几步。以 CentOS Stream 9 为例,先把下载好的压缩包上传到服务器,执行:
# 解压到指定目录 tar -xzf nacos-server-2.2.3.tar.gz -C /usr/local/ cd /usr/local/nacos # 单机模式启动 sh bin/startup.sh -m standalone启动后可以用jps命令查看 Java 进程,确认Nacos进程是否在运行。如果进程不在,就去logs/start.out看日志,最常见的原因就是端口被占用或 JVM 参数配置不正确。
Linux 下碰到的一个高频问题是防火墙。即使 Nacos 启动正常,其他服务器也访问不了 8848 端口,十有八九是防火墙没放行。CentOS 可以用:
firewall-cmd --permanent --add-port=8848/tcp firewall-cmd --reload3.3 Mac 安装 Nacos 2.1.1 的踩坑记录
Mac 装 Nacos 和 Linux 类似,但我装 2.1.1 时遇到过启动脚本的权限问题,提示Permission denied。原因是下载的压缩包没有执行权限,执行一下chmod +x bin/*.sh就能解决。还有一次启动后控制台能打开,但服务注册时客户端一直报连接超时,后来发现是因为 Mac 上装了多个版本的 JDK,Nacos 默认选到了一个高版本上,gRPC 端口(9848)被本机其他进程占用了。
Mac 用户如果用的 Apple Silicon(M1/M2 等),安装 Nacos 2.x 基本没有兼容性问题,它跑的是 Java 字节码,跟 CPU 架构无关。真正要注意的是别在 arm64 的终端里用 x86 版本的 JDK 跑,不然可能出现莫名其妙的崩溃。
4. 用 Docker 部署 Nacos:最省事但也有坑
4.1 Docker 单机容器一条命令跑起来
如果服务器上装了 Docker,用容器跑 Nacos 其实是最快的方式。以 2.2.3 版本为例:
docker run -d \ --name nacos \ -p 8848:8848 \ -p 9848:9848 \ -p 9849:9849 \ -e MODE=standalone \ nacos/nacos-server:2.2.3注意这里我把 9848 和 9849 端口也映射出来了,这个细节很多人漏掉。Nacos 2.x 服务端和客户端通信走的是 gRPC,服务端会占用主端口 8848 偏移 +1000 的 9848 端口用于 gRPC 通信,偏移 +1001 的 9849 用于 gRPC 服务间通信。如果你只映射了 8848,微服务注册时能连上,但后续心跳续约、配置监听都会失败,控制台里服务会一直显示不健康。
4.2 容器化部署必须设置的几个环境变量
Docker 部署 Nacos 时,环境变量很重要。除了MODE=standalone,生产环境一般还要设置这些:
docker run -d \ --name nacos \ -p 8848:8848 \ -p 9848:9848 \ -p 9849:9849 \ -e MODE=standalone \ -e SPRING_DATASOURCE_PLATFORM=mysql \ -e MYSQL_SERVICE_HOST=192.168.1.100 \ -e MYSQL_SERVICE_DB_NAME=nacos_config \ -e MYSQL_SERVICE_PORT=3306 \ -e MYSQL_SERVICE_USER=root \ -e MYSQL_SERVICE_PASSWORD=123456 \ -e NACOS_AUTH_ENABLE=true \ nacos/nacos-server:2.2.3设置SPRING_DATASOURCE_PLATFORM=mysql和对应的MYSQL_SERVICE_*参数后,Nacos 会把这些环境变量转成内部配置。如果打算用 MySQL 做存储,这些参数必须正确,否则容器起来以后会报数据库连接错误。
4.3 外部访问与数据持久化
容器部署后如果要从其他机器访问,防火墙和安全组要同时放行 8848、9848、9849 三个端口,这个前面提过了。另外一个容易被忽略的问题是数据持久化。默认情况下,容器内部的数据(包括 Derby 数据库文件)都随着容器销毁而消失。用 Docker 部署 Nacos 至少要把日志目录挂载出来,方便排查问题:
-v /opt/nacos/logs:/home/nacos/logs如果你用的是内置 Derby 存储,想保留数据,还要挂载数据目录。当然更推荐直接用 MySQL,数据在 MySQL 里,容器怎么销毁重建都不怕,这也是生产环境中用容器部署 Nacos 的主流方案。
5. 核心配置环节:数据库切换、配置中心玩法、国产数据库适配
5.1 为什么要从 Derby 切换到 MySQL
默认情况下 Nacos 把数据存在内嵌的 Derby 数据库里,这对本地开发很方便,零配置,启动即用。但 Derby 的定位是嵌入式数据库,不适合多实例共享。集群模式下每个节点的 Derby 数据是独立的,服务注册到某个节点后,其他节点再去查就查不到,这跟集群的“数据一致性”原则完全是背道而驰的。所以生产环境第一件事就是切换 MySQL。
切换前需要先建库。在 MySQL 中创建一个nacos_config数据库,然后执行 Nacos 解压目录conf下的mysql-schema.sql初始化脚本。如果你用的是 MySQL 8.x,脚本执行一般没问题,但要注意时区设置,URL 里最好加上serverTimezone=Asia/Shanghai,否则连接时会报时区错误。
5.2 application.properties 的修改要点
切换到 MySQL 时,需要修改 Nacos 服务端配置文件conf/application.properties。不要动默认以#注释掉的那部分,直接把下面这几行加进去或者取消注释:
spring.datasource.platform=mysql db.num=1 db.url.0=jdbc:mysql://localhost:3306/nacos_config?characterEncoding=utf8&connectTimeout=1000&socketTimeout=3000&autoReconnect=true&useUnicode=true&useSSL=false&serverTimezone=Asia/Shanghai db.user.0=root db.password.0=你的数据库密码改完保存,重启 Nacos。启动后如果你想确认是否真的切到了 MySQL,可以登录控制台,随便创建一个命名空间,再去 MySQL 里查nacos_config库下的tenant_info表,能看到刚创建的数据就是成功了。这比看日志更直观。
5.3 命名空间、Data ID、Group:配置中心三件套
配置中心是 Nacos 的招牌功能之一,很多人在里面对三个概念傻傻分不清。简单说:
- 命名空间(Namespace):环境隔离的维度,比如 dev、test、prod 各搞一个命名空间,互相不干扰。在配置中心里创建的配置都属于某个命名空间。
- Group:同一命名空间下的分组,默认值是
DEFAULT_GROUP。可以用来做应用维度的二次隔离,比如同一个环境里不同业务线用不同 Group。 - Data ID:配置文件的名字,格式一般是
服务名-环境.文件后缀,例如order-service-dev.yaml。
如果服务端配置和客户端配置文件都在,但客户端读不到配置,90% 是这三个维度没对上。客户端指定了namespace和group,服务端配置也必须在这个命名空间和分组下面,Data ID 必须完全一致。这种问题经常出现在环境切换之后,新环境里忘了建对应的配置。
5.4 配置动态刷新:让修改即时生效
Nacos 配置中心最大的卖点就是动态刷新,改完配置不用重启服务。实现上有两种方式:
方式一是在启动类或配置类上标注@RefreshScope注解,配合@Value注入配置项。配置变更后,Spring Cloud 会通过 Nacos Config 的长轮询机制感知到变化,自动刷新标注了@RefreshScope的 Bean。
方式二是用@NacosValue注解,并设置自动刷新:
@NacosValue(value = "${order.timeout:5000}", autoRefreshed = true) private int timeout;@Value 是从 Spring 属性源拿值,@NacosValue 是直接从 Nacos 配置获取。我个人更推荐 Spring Cloud 标准的@RefreshScope方式,这样整个项目的配置管理更统一,不会出现混用注解带来的维护成本。
有一个坑值得注意:如果你改了配置,控制台显示发布成功,但应用日志里没有变化,先检查客户端依赖版本和spring.config.import的配置,这个在第六章会详细说。
5.5 国产数据库适配:达梦、DB2 等到底行不行
热词里专门提到了 Nacos 适配达梦数据库。官方在 2.2.1 版本以后确实加强了这块的支持,社区也有适配达梦的方案。具体思路很简单:Nacos 数据库访问层是在DataSource之上做了插件化扩展,你只要实现了对应数据库方言的支持,在数据源配置里指定即可。但实际操作中,达梦和 MySQL 的 SQL 语法差异会让默认的 Schema 脚本初次执行时出错,需要手工调整一部分建表语句,这个比较费功夫。
官方文档里明确支持的数据库是 MySQL 和 Derby,达梦属于社区适配范畴。如果你没有专门的 DBA 或运维资源去搞适配,生产环境最好不要冒险用达梦跑 Nacos,规规矩矩用 MySQL 才是稳妥方案。至于 DB2,目前官方没有直接支持,社区方案也不成熟,建议避免。
实际项目里常见架构是:Nacos 用 MySQL 存数据,你的业务数据库用达梦或 DB2。这个组合非常稳定,既不耽误注册中心和配置中心工作,又满足了业务系统的国产化数据库要求。搞清楚 Nacos 自身的数据存储和业务数据存储是可以分离的,很多架构上的纠结就迎刃而解了。
6. 常见问题与排查技巧实录
6.1 启动失败的几个高频原因
启动失败是遇到最多的问题,我把高频原因整理成一个速查表:
| 现象 | 常见原因 | 处理方式 |
|---|---|---|
| 控制台提示 started successfully 但页面打不开 | 8848 端口被占用,或 Nacos 实际启动失败 | 检查logs/start.out,确认端口netstat -ano | findstr 8848 |
| 集群模式启动报节点列表为空 | 没加-m standalone,或cluster.conf没配置 | 单机加-m standalone;集群配置好节点列表 |
| 数据库连接失败 | 密码错误、MySQL 未启动、URL 时区参数缺失 | 检查application.properties中db.*配置,控制台输入密码测试连接 |
| 内存不足导致启动崩溃 | JVM 堆内存配置过大 | 修改bin/startup.sh或startup.cmd中的 JVM 参数,适当降低默认堆内存 |
有一个细节常被忽略:Nacos 默认 JVM 参数是按 4G 内存配置的,很多本地机器根本给不到那么多,启动时就会报内存溢出。Windows 下在bin/startup.cmd里找JAVA_OPT相关的设置,调小-Xms和-Xmx就行。
6.2 服务注册不上或者服务一直显示不健康
客户端服务启动后,在 Nacos 控制台服务列表里看不到服务,或者看到服务但实例显示不健康,这种情况非常多。常见有两类原因。
第一类是网络问题。客户端机器访问不到 Nacos 服务端,或者因为 Nacos 2.x 需要 9848 端口做 gRPC 通信,但这个端口没放开。解决方法是先确认客户端所在的机器能telnet 服务端IP 8848和telnet 服务端IP 9848,这两个端口都能通才行。注意很多云服务器安全组只放行了 8848,gRPC 端口忘了放行,这就是服务注册控制台能看到,但实际调不通的经典原因。
第二类是配置问题。比如客户端配置了命名空间,但 Nacos 上的服务注册到默认命名空间去了,两边不一致自然找不到。排查时先看客户端日志里 Nacos 注册中心输出的 Registered 服务名是不是你期望的那个,一般都有明确报错。
6.3 配置中心读不到配置,no spring.config.import 报错
这个报错在 Spring Cloud 2020.0 及以上版本特别常见。Spring Cloud 新版本把 Nacos Config 默认从 Bootstrap 上下文加载改成了需要手动指定spring.config.import。如果你的项目用的是spring-cloud-starter-alibaba-nacos-config2.2 以上版本,并且报错信息里出现:
No spring.config.import property has been defined解决方法是把 Nacos 配置中心当成一个额外的配置源引入。在项目的application.yml里加上:
spring: application: name: order-service config: import: optional:nacos:order-service.yaml?group=DEFAULT_GROUP&refreshEnabled=true cloud: nacos: config: server-addr: 127.0.0.1:8848 file-extension: yaml核心就是spring.config.import这个属性。optional前缀表示即使 Nacos 上不存在这个配置,应用也能正常启动,避免因为配置文件拉取失败阻塞整个服务启动。这个错误真的很常见,尤其新手从老版本教程复制配置过来,折腾半天发现是版本问题。
6.4 安全风险:namespaces 未授权访问漏洞
搜索引擎上“nacos namespaces未授权访问漏洞【原理扫描】”这个热词说明很多人已经在安全扫描中踩到这个问题了。Nacos 控制台如果没开鉴权,攻击者只要能访问到 8848 端口,就能通过接口直接访问或篡改命名空间、配置和服务注册信息,后果很严重。
解决办法是开启 Nacos 鉴权。在application.properties里加:
nacos.core.auth.enabled=true nacos.core.auth.plugin.nacos.token.secret.key=你的base64编码密钥(至少32字节) nacos.core.auth.server.identity.key=serverIdentity nacos.core.auth.server.identity.value=safeValue这里的 token secret key 要注意,官方建议用 Base64 编码后的长字符串,不要太简单。开启了鉴权之后,客户端连接 Nacos 也要带上用户名密码,在客户端的配置里加上:
spring: cloud: nacos: discovery: username: nacos password: 你的密码 config: username: nacos password: 你的密码这个问题建议在部署 Nacos 的第一天就处理掉,不要等服务被扫描出来再补救。
6.5 集群模式下节点列表和节点信息的查看
集群模式部署后,想知道集群节点状态,可以直接访问 Nacos 自带的 API:
curl -X GET 'http://127.0.0.1:8848/nacos/v1/core/cluster/nodes?pageNo=1&pageSize=10'返回的是集群节点的 IP、端口、状态、选主信息等。这个接口在排障时特别有用,比如某台节点挂了,能直接从这里看到。集群模式还有一个高频问题:控制台登录后服务列表为空,其他节点能看到服务,但某一个节点看不到,说明节点之间的数据同步有问题,大概率是你用的存储还是 Derby。集群环境下必须切 MySQL,这是绕不开的前提。
Nacos 集群内部的选主机制基于 Raft 算法,通过 Netty 框架实现节点间通信。
提示:热词里“Nacos中有用到netty吗”的答案是:Nacos 2.x 的 gRPC 通信底层就是用 Netty 实现的,所以客户端和服务端之间那层高性能网络通信,Netty 功不可没。
6.6 Nacos 与 Dubbo、Knife4j 的整合思路
最后聊一下热词里出现的“dubbo、nacos”和“微服务整合 knife4j nacos”。Dubbo 从 2.7 版本开始支持使用 Nacos 作为注册中心,配置很简单:
dubbo: registry: address: nacos://127.0.0.1:8848整合后,Dubbo 服务提供者和消费方都会自动注册到 Nacos,由 Nacos 负责服务发现和健康检查。这种组合在中小团队非常流行,因为它比传统的 ZooKeeper 模式多了一个配置中心的能力,基础设施更简洁。
Knife4j 是 Swagger 文档增强工具,和 Nacos 的整合主要是通过网关统一聚合微服务的接口文档。常见做法是网关服务通过 Nacos 发现下游服务,Knife4j 的聚合模式会自动从 Nacos 服务列表拉取各个服务的文档请求路径。这样运维和前端不用记忆每个服务的独立地址,一个网关入口就能预览全部接口文档。整合的关键点还是网关能正确通过 Nacos Discovery 解析服务名,其余配置按 Knife4j 文档来就好。
最后再分享一个小技巧。很多人在 Windows 上把 Nacos 装好后,为了图省事直接双击startup.cmd,结果每次都要手动去关黑窗口,Nacos 还时常用着用着自己就停了。我的建议是设置成 Windows 服务或者用工具托管,在 Linux 上用 systemd 托管,生产环境更是要托管起来。这样 Nacos 掉线能自动重启,日志也有统一管理,比裸跑进程稳定太多了。
另外,Nacos 的版本升级不要盲目追新。如果项目稳定跑得好好的,没必要频繁升级,尤其不要跨大版本升级。我见过一个项目从 1.4 直接升 2.2,结果一堆客户端服务要跟着改配置,折腾了整整一周。Nacos 这类基础组件属于“稳定压倒一切”的范畴,选好版本后尽量保持一致,能不动就不动。