
前几天群里又有人问服务一多各个服务的地址都得手动写死在配置文件里每次改个端口或者迁移机器都要重新打包部署有没有什么好办法我的回答基本只有一个把Nacos用起来。NacosDynamic Naming and Configuration Service是阿里开源的一款服务发现与配置管理平台在微服务架构里同时扮演两个角色——注册中心和配置中心。这篇教程我尽量写得“保姆级”一点从零开始讲清楚Nacos是什么、怎么安装、怎么接入Spring Cloud使用也会把Windows和Linux两套安装流程、数据存储切换、外部访问、动态刷新、安全加固这些大家问得最多的问题一并整理出来。不管是刚接触微服务的新手还是已经在生产环境里踩过坑的开发者这篇都可以作为一份常备手册来参考。1. 一句话定位Nacos到底是什么能解什么愁1.1 注册中心相当于微服务的通讯录微服务架构里服务会被拆成很多个独立进程比如订单服务、用户服务、库存服务。以前的做法是把每个服务的IP和端口写死在另一些服务的配置里但服务一旦扩容、缩容或者迁移机器配置就要跟着改改了还要重启非常痛苦。Nacos作为注册中心相当于一本“动态通讯录”。每个服务启动的时候主动把自己的IP、端口、服务名上报到Nacos调用方不再关心目标服务具体在哪台机器上而是直接问Nacos“用户服务现在有哪些实例可用”。Nacos返回可用列表调用方再从列表里挑一个发起请求。这样服务上下线、扩缩容都是自动感知的不需要人工改配置。这个机制在微服务里称为“服务发现”。Nacos在实现上区分了临时实例和持久化实例临时实例通过心跳续约服务挂了超过一定时间会自动剔除持久化实例则依赖主动注销适合一些不适合被自动摘除的场景。默认情况下我们都是用临时实例心跳机制保证了列表的实时性和准确性。1.2 配置中心相当于能热更新的配置仓库除了服务发现Nacos还能管理配置。传统项目里配置写在application.yml里改一个数据库连接串都要重新打包、上传、重启。在Nacos配置中心里配置被集中保存在服务端应用启动时从Nacos拉取而且运行期间配置一变客户端能实时感知并刷新不用重启服务。这里解决的是“配置和代码分离”以及“配置动态生效”两个问题。环境变量、开关位、线程池参数、限流阈值这类频繁调整的内容特别适合放到配置中心。Nacos在配置上还支持多环境、多分组、灰度发布、版本回滚这些在后面的使用部分会展开讲。很多团队用Nacos之后第一感受就是“再也不用因为改一个参数去重新发版了”。这种体验在过去是不可想象的也是Nacos能成为微服务标配的重要原因。1.3 什么时候该上Nacos什么时候可以不折腾我也遇到过有人刚写了个小项目就非要上Nacos说实话没必要。单体应用或者只有两三个服务的项目配置中心带来的收益小于维护成本直接用本地配置就行。但如果你的服务数量开始多起来服务之间互相调用变得混乱或者经常要为环境切换、参数调整频繁发布Nacos的注册中心和配置中心能力就能直接把这类痛点消掉。从技术选型角度看Nacos对比同类产品也有优势相比EurekaNacos自带控制台和配置管理功能更全相比ConsulNacos在亚太区用户基数大中文资料丰富和Spring Cloud Alibaba的集成也最顺畅。如果你已经用了DubboNacos同样可以充当Dubbo的注册中心一套组件同时兼容两套生态。简单说Nacos适合的是“服务多了、配置乱了、发布烦了”的团队。判断标准很朴素如果你正被服务地址管理或者配置改动人折腾那就该把它用起来。2. 拿到Nacos版本选择、环境准备与下载2.1 环境依赖其实只有JDKNacos服务端本身是一个Java应用所以安装它只需要准备JDK。这里有个容易被忽略的细节Nacos 2.x版本要求JDK 8及以上建议直接用JDK 8或者JDK 11版本太新的JDK比如17、21在实际使用中偶尔会遇到一些兼容性问题不是绝对不行但没必要给自己找麻烦。检查JDK环境很简单在命令行执行java -version如果提示找不到命令需要先配置JAVA_HOME环境变量。Windows下在“系统属性-环境变量”里新增JAVA_HOME指向JDK安装目录再把%JAVA_HOME%\bin加到Path里。Linux下可以编辑/etc/profile加入export JAVA_HOME/usr/local/jdk8 export PATH$JAVA_HOME/bin:$PATH配好后执行source /etc/profile让配置生效再验证一次java -version即可。这一步卡住的基本都是环境变量没配对路径别带多余空格就行。2.2 版本怎么选别闭眼装最新的Nacos目前主流的版本线是1.x和2.x。1.x虽然稳定但已经处于维护状态新功能基本都在2.x上。2.x引入了gRPC通信客户端和服务端之间的长连接性能更好推送延迟也更低生产环境建议直接用2.x。具体版本号怎么选我建议去Nacos的GitHub Releases页面看选择最新的稳定版也就是不带alpha、beta、RC后缀的版本。比如2.3.2这样的版本就是可以直接用的。不要下载源码包自己编译直接选nacos-server-xxx.zip或nacos-server-xxx.tar.gz这类已经打好的发布包。有一点要注意Nacos客户端和服务端的版本不要相差太远。如果你的Spring Cloud Alibaba版本比较老配套的Nacos客户端可能是1.4.x那服务端可以不升级到2.2以上。版本兼容这事在后面的避坑章节我做了个速查表可以直接参考。2.3 两种下载方式与目录结构下载Nacos有两种常用方式一是从GitHub Releases页面手动下载二是用命令行工具直接拉取。比如在Linux上wget https://github.com/alibaba/nacos/releases/download/2.3.2/nacos-server-2.3.2.tar.gz tar -zxvf nacos-server-2.3.2.tar.gz国内网络如果下载慢可以找一下镜像站或者用加速地址但注意校验压缩包的完整性避免解压到一半报错。解压后目录结构是这样bin/启动和关闭脚本startup.sh和startup.cmdconf/配置文件包括application.properties、mysql-schema.sql等logs/运行日志目录排错基本都靠这里data/内嵌存储的数据文件目录首次启动会自动生成了解目录结构很重要后面改配置、看日志、换数据库都要用到这些路径。3. 保姆级安装实操Windows / Linux / MySQL3.1 Windows下启动双击脚本还是命令行Windows下安装Nacos非常简单。把下载好的zip包解压到一个没有中文和空格的路径下比如D:\nacos然后进入bin目录找到startup.cmd。这里有个关键选择默认执行startup.cmd会以集群模式启动而本地开发环境没有配置集群启动会失败。所以本地一定要指定单机模式启动startup.cmd -m standalone如果命令行不熟悉也可以手动设置环境变量NACOS_MODEstandalone再执行脚本。启动成功后控制台会输出日志路径打开浏览器访问http://localhost:8848/nacos就能看到登录页面默认账号密码都是nacos。第一次启动如果遇到闪退十有八九是JAVA_HOME没配对或者端口8848被占用。排查方法是进入logs/start.out看报错内容这个日志记录了启动过程的全部关键信息比瞎猜管用。3.2 Linux下安装与端口开放CentOS Stream 9也能跑Linux下的安装流程更贴近生产环境也是面试和工作中最常见的操作方式。以CentOS Stream 9为例我把完整流程列一遍# 1. 下载并解压 wget https://github.com/alibaba/nacos/releases/download/2.3.2/nacos-server-2.3.2.tar.gz tar -zxvf nacos-server-2.3.2.tar.gz mv nacos /usr/local/nacos # 2. 单机模式启动 cd /usr/local/nacos/bin sh startup.sh -m standalone # 3. 确认启动结果 cat /usr/local/nacos/logs/start.out启动后本机访问没问题但外部机器访问不到很大概率是防火墙没放行。CentOS默认启用firewalld需要开放8848端口firewall-cmd --zonepublic --add-port8848/tcp --permanent firewall-cmd --reloadNacos 2.x还有一个隐藏要求客户端除了连接8848还会通过gRPC连接9848端口88481000。如果只放行8848外部客户端会发现控制台能打开但服务注册不上。所以务必把9848也一起放行firewall-cmd --zonepublic --add-port9848/tcp --permanent firewall-cmd --reload如果你用的是云服务器还要到安全组里加同样的规则云平台安全组和系统防火墙是两层概念少放一个都会导致外部访问失败。3.3 别偷懒用默认存储把数据切到MySQL再做正经事Nacos 2.x默认使用内嵌的Derby数据库存储配置和服务信息。Derby的好处是零配置开箱即用坏处是不适合多实例共享数据。如果你部署集群多个Nacos节点各存各的Derby数据就对不上了。所以生产环境必须换成MySQL。操作流程不复杂第一步创建数据库并导入Nacos官方SQL脚本mysql -uroot -p -e CREATE DATABASE nacos_config DEFAULT CHARACTER SET utf8mb4; mysql -uroot -p nacos_config /usr/local/nacos/conf/mysql-schema.sql第二步编辑conf/application.properties把下面几行放开并修改spring.datasource.platformmysql db.num1 db.url.0jdbc:mysql://127.0.0.1:3306/nacos_config?characterEncodingutf8connectTimeout1000socketTimeout3000autoReconnecttrueuseUnicodetrueuseSSLfalseserverTimezoneAsia/Shanghai db.user.0你的数据库用户名 db.password.0你的数据库密码注意MySQL 8的驱动问题。Nacos 2.x自带MySQL 8驱动一般不用额外处理如果你用的是老版本Nacos可能需要手动引入mysql-connector-java。还有一点serverTimezone参数务必设置否则可能因为时区问题报错。第三步重启Nacossh /usr/local/nacos/bin/shutdown.sh sh /usr/local/nacos/bin/startup.sh -m standalone重启后进入控制台随便改一个配置再查MySQL里的config_info表能看到记录就说明切换成功了。3.4 外部访问与默认账号安全一台服务器部署给团队使用的正确姿势外部访问Nacos不只是开个端口那么简单还有一层安全因素要先处理。很多团队图省事Nacos装完直接用默认的nacos/nacos登录还把8848端口直接暴露到公网这是非常危险的操作。Nacos历史上出过多个安全漏洞比较典型的是/nacos/v1/auth/users接口的未授权访问漏洞攻击者不需要登录就能调用接口添加用户、获取用户列表。这类漏洞原理上就是鉴权机制不完善所以加固的第一条就是开启鉴权。在conf/application.properties里修改以下配置nacos.core.auth.enabledtrue nacos.core.auth.plugin.nacos.token.secret.key这里填写一个长度不小于32字节的Base64编码字符串生成密钥可以用一条命令openssl rand -base64 32开启鉴权后所有客户端连接也需要带上用户名密码。Spring Cloud客户端需要在配置里加spring: cloud: nacos: username: nacos password: 你修改后的密码然后立刻登录控制台修改默认密码路径是“控制台-用户名-修改密码”。外部访问方面最稳妥的做法是把Nacos部署在内网只允许应用服务器访问如果确实需要公网访问控制台建议前面再加一层反向代理并配置IP白名单不要裸奔。如果你用的是K8s或Rancher部署Nacos外部访问要同时暴露8848和9848两个端口比如用NodePort方式把两个端口都映射出去只映射8848会导致服务注册失败这个细节我已经见过不少人踩坑了。4. 接入Spring Cloud把注册中心和配置中心用起来4.1 注册中心接入三步让服务完成“自报家门”Nacos装好只是第一步真正发挥作用的是应用接入。以Spring Cloud项目为例注册中心的接入非常简单。第一步在pom.xml里引入依赖dependency groupIdcom.alibaba.cloud/groupId artifactIdspring-cloud-starter-alibaba-nacos-discovery/artifactId /dependency第二步修改application.ymlspring: application: name: order-service cloud: nacos: server-addr: 127.0.0.1:8848 username: nacos password: nacos第三步在启动类上加EnableDiscoveryClient注解。实际上Spring Cloud Alibaba的版本较新时这个注解可以不加也能注册但加上更保险、更明确。启动服务后打开Nacos控制台的“服务管理-服务列表”就能看到order-service已经出现在列表里点击详情还能看到IP和端口。另一个服务要调用它直接通过服务名负载均衡来调用完全不用写死地址RestController public class TestController { Autowired private RestTemplate restTemplate; GetMapping(/call) public String call() { return restTemplate.getForObject(http://order-service/hello, String.class); } }这里RestTemplate需要配合LoadBalanced注解开启负载均衡能力。整个过程最直观的感受就是以后任何服务地址变化都跟调用方无关了。4.2 配置中心接入与动态刷新改配置不用再重启配置中心接入比注册中心稍微绕一点但核心思路很清晰把配置文件从项目里挪到Nacos上应用启动时拉取运行时自动刷新。第一步引入依赖dependency groupIdcom.alibaba.cloud/groupId artifactIdspring-cloud-starter-alibaba-nacos-config/artifactId /dependency第二步在bootstrap.yml里配置Nacos地址和dataIDspring: application: name: order-service cloud: nacos: config: server-addr: 127.0.0.1:8848 file-extension: yaml需要注意Spring Cloud 2020.0版本之后bootstrap机制默认关闭很多新项目用application.yml配合spring.config.import来导入Nacos配置spring: config: import: nacos:order-service.yaml两种方式选一种即可要看你的Spring Cloud版本。这地方报错“config import failed”基本都是版本方案选错了。第三步在Nacos控制台新建配置dataID填order-service.yaml配置内容写你需要动态管理的参数比如app: switch: true thread-pool-size: 10然后在代码里使用RefreshScope配合Value实现自动刷新Component RefreshScope public class AppConfig { Value(${app.switch:true}) private boolean switchEnabled; Value(${app.thread-pool-size:10}) private int threadPoolSize; }修改Nacos上的配置并发布几秒内应用里的值就会更新不用重启。这就是大家常说的“热更新”、“动态刷新”。实际生产里我经常把线程池参数、超时时间、功能开关都放这边调整起来效率高很多。4.3 命名空间、分组与多环境隔离如果你的项目分开发、测试、生产环境肯定不希望配置混在一起。Nacos用三层概念来隔离配置和服务Namespace命名空间隔离环境最常用。不同环境用不同namespace相互之间数据完全隔离。Group分组同一个namespace下再按业务线或应用类型分组默认是DEFAULT_GROUP。DataID配置唯一标识最后的配置文件名通常用服务名-环境.yaml这类规范命名。实际配置里命名空间ID不是填名称而是填系统生成的ID字符串。在namespace里切换到对应环境客户端配置对应namespace: 环境ID即可spring: cloud: nacos: server-addr: 127.0.0.1:8848 namespace: dev-namespace-id有个容易踩的坑如果不填namespace默认使用的是public命名空间ID是空字符串。所以经常有人说“我在控制台能看到配置但服务读不到”多半是namespace没对上。4.4 权重、下线、灰度与回滚控制台上的生产级功能注册中心的核心能力不只是服务发现还包括流量控制。在服务详情页每个实例都可以设置权重。权重越高被调用方选中的概率越大。发布新版本的时候我习惯先把新实例权重调到很低让它接收少量流量观察日志确认没问题再慢慢把权重调上去这就是最朴素的灰度发布。如果某个实例有问题需要临时摘除可以点击“下线”服务会从可用列表里摘掉但保留注册数据排查完再点上线比直接停服务优雅得多。配置中心也一样。你可以对某个配置做历史版本管理发布错了直接一键回滚到上一个版本。发布配置的时候还支持Beta发布选一部分IP先生效验证通过再全量发布。这些功能在控制台都有对应入口操作非常直观属于那种“你知道了就会想用”的功能。5. 实际操作中容易踩的坑与排查清单5.1 启动就失败先查这三件事第一闪退。Windows下双击startup.cmd直接闪退99%是JAVA_HOME没配好。命令行先执行java -version如果正常再用echo %JAVA_HOME%检查变量路径里有空格也会出问题建议把JDK装到无空格目录。第二端口被占用。8848起不来用netstat -ano | findstr 8848Windows或者lsof -i:8848Linux看谁占了端口。这种情况常见于已经跑过其他服务或者Nacos重复启动。第三Derby数据锁冲突。如果是用默认Derby跑了多个实例或者多次初始化日志里会出现database is locked之类的报错。解决办法是停掉所有Nacos进程删除data目录下的derby数据目录再重启。这也是我强烈建议切换到MySQL的原因之一Derby在并发和数据管理上太弱了。5.2 服务注册不上、客户端连不上怎么查服务注册不上是使用Nacos最高频的问题。排查顺序建议从简单到复杂先看网络通不通curl http://127.0.0.1:8848/nacos/v1/ns/operator/metrics能返回JSON说明服务端正常。再看客户端配置server-addr对不对namespace有没有填错账号密码有没有开鉴权导致连不上。最后看版本对不对。Nacos 2.x的客户端通过gRPC与服务端通信如果服务端是2.x而客户端依赖被降级到1.x会出现各种诡异问题。检查依赖树mvn dependency:tree -Dincludescom.alibaba.nacos如果版本不对排除旧依赖统一版本。这里有一个通用原则Spring Cloud Alibaba、Spring Cloud、Nacos客户端三者要配对使用不要各用各的版本。5.3 配置死活不刷新、读不到配置配置相关的问题核心就是dataID、group、namespace三要素要对齐。Nacos客户端查找配置的顺序是namespacegroupdataID任何一个不匹配就查不到。还有一个新手高发问题Value的类没有加RefreshScope或者加了但没有通过Spring容器管理比如自己new了一个对象。RefreshScope会为配置类生成代理刷新时会重建bean如果绕开了代理自然感知不到更新。如果你配置了多个配置文件要注意加载优先级。spring.cloud.nacos.config.extension-configs和shared-configs用来引入扩展配置这些配置的优先级低于主dataID同名的key会被主配置覆盖。弄清楚优先级规则能避免很多“配置怎么不生效”的困惑。5.4 安全漏洞与加固未授权访问要当回事前面提过Nacos的未授权访问漏洞我再展开说下。这类漏洞主要影响直接暴露在公网、并且没有修改默认密码的Nacos。攻击者可以未授权调用用户管理接口添加一个自己的账号然后登录控制台读取所有服务的配置和注册信息危害极大。加固步骤整理成了一张清单修改默认密码不要用nacos/nacos。开启鉴权nacos.core.auth.enabledtrue配置足够长的token密钥。控制台和API不要直接暴露公网用内网白名单反向代理。升级到新版本官方在2.2.1以后对鉴权模块做了大量加固老版本建议尽快升级。定期检查users表看有没有异常账号。如果你在扫描报告里看到“nacos namespaces未授权访问漏洞”这类字样不用慌按上面五步处理基本就能消除。5.5 版本兼容速查表照着选就少踩坑版本混用是Nacos使用中最隐蔽的坑。我整理了一份常见搭配覆盖大部分项目场景Spring Cloud Alibaba版本Spring Cloud版本推荐Nacos服务端说明2.2.x.RELEASEHoxton.SR系列1.4.x老项目经典组合稳定优先2021.0.1.02020.0.x1.4.2或2.0.x过渡期常用2021.0.5.02021.0.x2.0.3或2.2.x用户量较大资料丰富2023.0.1.x2023.0.x2.3.x新项目建议gRPC体验完整具体对应关系还是要以官方发布的版本说明为最终依据但这张表能帮你在绝大多数组合里选到一个不会错的方案。记住一个原则不要随便升级Nacos服务端到最新而要结合自己项目的Spring Cloud Alibaba版本决定。说几个我在实战里印象比较深的细节。Nacos控制台首次登录后最好立刻改密码这不是小题大做而是无数次安全扫描得来的教训。配置中心动态刷新这个功能日常用起来非常爽但生产环境改动前最好先开Beta发布验证别图省事直接全量推。还有外部访问一定把8848和9848一起暴露少了9848客户端能打开页面但就是注册不上这是2.x最容易被忽略的特性。如果你刚接触Nacos建议先在自己电脑上跑一遍上面的安装流程再用Spring Cloud写两个小服务互相调用试试整个过程下来基本就摸透了。后续如果要用到集群、持久化、限流这些进阶能力基于这篇文章里的基础操作再去看官方文档会顺畅很多。