Java框架 SpringCloud 快速入门: Nacos 服务多级存储模型

发布时间:2026/10/8 6:48:24
Java框架 SpringCloud 快速入门: Nacos 服务多级存储模型 概述服务注册进 Nacos 之后一个服务往往有多个实例这些实例如果分散在全国不同的机房调用方该怎么选Nacos 在「服务 → 实例」之间又插了一层「集群」就是为了让调用尽量落在同机房。纲要三级结构服务service/ 集群cluster/ 实例instance为什么需要集群跨机房调用延迟高同机房优先才能压住响应时间给实例配置集群spring.cloud.nacos.discovery.cluster-name验证Nacos 控制台里的集群分组与实例分布集群划分的实践含义集群名怎么取、什么时候分、什么时候不用配与 namespace 的区别环境维度 vs 机房维度本篇只解决「集群是前提」同机房优先要靠 NacosRule —— 留给下一篇常见坑消费者没配集群、大小写不一致、指望跨机房零延迟、改完不重启三级结构服务 → 集群 → 实例先回忆一下已经用过的两层结构。userservice提供用户查询orderservice提供订单查询它们都是服务userservice部署了8081、8082、8083三个进程三个都是userservice的实例。所以一开始是两层一个服务包含多个实例。单机房部署的问题在于风险集中。所有实例都放在一个机房里机房一旦出问题断电、断网、甚至更严重的灾害整个服务就全挂了。解决办法是把同一个服务的多个实例分散到不同机房—— 阿里、京东这类业务就是这么干的上海、杭州、北京各放一批。这就是容灾。但分散之后带来一个新问题杭州的orderservice要调userservice它可以调杭州本地的实例也可以调北京的实例该怎么选Nacos 的答案是在「服务」和「实例」之间加一层「机房/地域」的划分把同一机房内的多个实例称为一个集群。于是分级模型变成三级服务 userservice集群 HZ杭州机房集群 SH上海机房实例 127.0.0.1:8081实例 127.0.0.1:8082实例 127.0.0.1:8083三级各自代表什么别混层级对应实体说明服务 service同一个应用userservice由spring.application.name决定集群 cluster地理 / 机房维度的划分HZ、SH同一机房内的实例归为一组实例 instance一个具体进程IP:port真正的网络终点为什么要引入集群这不是为了概念好看。回到那个问题杭州机房的orderservice要访问userservice本地机房有实例外地机房也有实例选哪个答案是本地优先。原因很直接同机房的访问走的是局域网距离短、链路少延迟通常在毫秒级以内一旦跨集群比如从杭州调到广州或北京物理距离几百上千公里往返延迟会高出一两个数量级。所以服务调用应该尽可能落在本地集群只有本地集群不可用时才退到其他集群。Nacos 引入集群概念本质就是为了减少跨集群调用的比例而不是消灭跨集群调用。优先本地不可用时才走orderservice杭州集群userservice HZ 实例userservice SH 实例还要注意一点现在工程里的实例集群名默认是default。在 Nacos 控制台点进服务详情就能看到 —— 集群名称DEFAULT也就是没有划分集群。下面来给它配上。给实例配置集群修改user-service的application.yml在spring.cloud.nacos下加discovery.cluster-nameserver:port:8081spring:application:name:userservicecloud:nacos:server-addr:localhost:8848discovery:cluster-name:HZ# 集群名称HZ 表示杭州cluster-name的值是自定义的HZ只是「杭州」的缩写你写hangzhou、hz-1、room-a都一样Nacos 不解释它的语义只按字符串分组。启动两个user-service实例它们就都归到了HZ集群。如果要再起一个属于上海集群的实例有两种写法改一份application.yml把cluster-name写成SH再启动不动配置文件用启动参数覆盖java-jaruser-service.jar-Dserver.port8083-Dspring.cloud.nacos.discovery.cluster-nameSH用 IDEA 调试时是在 Run Configuration 的 VM options 里填-Dserver.port8083 -Dspring.cloud.nacos.discovery.cluster-nameSH这里有个坑用 IDEA 启动多个实例时别在同一个实例上反复重启改集群名。比如你已经在8081上跑了一个实例把它改回SH再重启那这个端口上的实例就从 HZ 跑到 SH 去了原来的 HZ 实例没了。要多机房模拟就多复制几份启动配置各自固定集群名。对应到order-service写法一样只是值不同server:port:8088spring:application:name:orderservicecloud:nacos:server-addr:localhost:8848discovery:cluster-name:SH# 订单服务部署在上海机房上文的配置位置以讲义为准。本工程终态代码里user-service的 Nacos 连接信息放在bootstrap.ymlspring.application.name、spring.profiles.active、spring.cloud.nacos.config集群属性加在application.yml的spring.cloud.nacos.discovery下即可两者最终都会合并进环境。终态仓库里这段cluster-name目前是注释状态# discovery:# cluster-name: HZ它被留在user-service/src/main/resources/application.yml里只是因为仓库快照没有开放这段演示配置实际演示时按上面取消注释即可。验证在 Nacos 控制台看集群分组实例启动后打开 Nacos 控制台默认http://localhost:8848/nacos走一遍左侧菜单进入服务管理 → 服务列表找到userservice列表里会显示「集群数目」这一列点服务名进详情看到按集群分组的实例分布。预期看到的内容大致是这样服务名: userservice 集群数目: 2 集群: HZ - 127.0.0.1:8081 (临时实例) - 127.0.0.1:8082 (临时实例) 集群: SH - 127.0.0.1:8083 (临时实例)到这一步实例的集群属性就配好了。服务列表里的「集群数目」从 1 变成 2就是配置生效的直接证据。集群划分的实践含义cluster-name一旦配下去工程里就多了一个维度几个实际问题得想清楚。集群名怎么取没有硬性规范机房、可用区AZ、区域名都行业务自定义。常见做法是用城市/机房缩写HZ、SH或物理机房代号room-a。关键是同一个机房的实例必须写完全相同的字符串。什么时候需要划分只有实例跨机房、跨可用区、跨区域部署时才需要。单体机房部署时完全可以不配Nacos 会把实例都算到DEFAULT集群里功能不受影响。划分带来什么它是后续「同机房优先」的前提条件。不配集群所有实例都在一个默认集群里也就无所谓同机房优先了。至于「怎么让消费者优先调同机房」那不是本节的配置能完成的 —— 默认的ZoneAvoidanceRule并不会按同集群优先挑实例需要把负载均衡规则换成NacosRule。所以这里只要记住集群划分是先决条件策略配置在下一篇。和 namespace环境隔离是一回事吗不是。这两个概念层级完全不同初学者最容易把它们混在一起。维度cluster集群namespace命名空间解决的问题同一环境内机房/可用区维度的就近调用多环境之间的资源隔离dev / test / prod划分依据物理位置机房、区域环境开发、测试、生产配置项spring.cloud.nacos.discovery.cluster-namespring.cloud.nacos.discovery.namespace是否隔离资源否同一命名空间内互相可见是不同命名空间的服务默认互相看不见典型值HZ、SH、room-anamespace 的 IDUUID一句话cluster 是同一环境内的机房维度namespace 是环境维度。生产环境里的userservice和测试环境里的userservice应该用 namespace 隔开而生产环境内部的杭州、上海机房之间才用 cluster 区分。层级不同别混用。常见坑只给提供者配了cluster-name。userservice配了 HZ/SHorder-service没配还在DEFAULT那么「同机房优先」根本无从谈起 —— 消费端自己都不在任何集群里拿什么跟别人比。要玩同机房优先消费者和提供者两边都得配。集群名大小写不一致。HZ和hz在 Nacos 看来是两个不同的集群会被拆成两组永远命中不了对方。约定好命名后全工程统一。跨机房却期望零延迟。集群分组只降低「跨机房调用的比例」不改变跨机房调用本身的网络开销。真出现本地集群不可用、流量全打到外地机房的情况延迟该高还是高。实例分错集群改完不重启。cluster-name是启动时注册到 Nacos 的改完必须重启服务才会以新集群重新注册。热改配置文件不生效。API / 配置速览项内容配置项spring.cloud.nacos.discovery.cluster-name默认值DEFAULT不配时所有实例同属一个默认集群取值自定义字符串同机房实例必须一致覆盖方式配置文件写死或 VM 参数-Dspring.cloud.nacos.discovery.cluster-nameSH生效时机服务启动注册时改后需重启验证入口Nacos 控制台 → 服务管理 → 服务列表 → 详情按集群分组下游依赖同机房优先需切换到com.alibaba.cloud.nacos.ribbon.NacosRule官方文档Nacos 官方文档 - 服务发现Spring Cloud Alibaba - Nacos DiscoveryNacos GitHub总结多级存储模型把原来的「服务 → 实例」两层扩成「服务 → 集群 → 实例」三层多的这一层代表机房/地域。它要解决的是微服务跨机房部署后调用方在本地机房和外地机房之间怎么选的问题 —— 本地优先因为局域网延迟远低于跨机房。配置本身只有一行spring.cloud.nacos.discovery.cluster-name。真正需要记住的是三件事集群名是纯字符串分组大小写必须统一单体机房可以不配跨机房才需要集群划分只是前提把「同一集群优先」真正落到调用链上还得靠 NacosRule。另外别把 cluster 和 namespace 搞混前者是环境内的机房维度后者是环境之间的隔离维度。