Chapter 05
自测题库
前四章从概念建到原理再到选型。这一章不教新东西——它逼你回忆和判别。 三层梯度共 16 题,最后一层是跨章场景题,能答上才算把那条脊柱真正内化了。
怎么用这一章
- 所有答案集中在页面最底部的一个折叠块里——先把全部题做完再展开,中途偷看等于把自测降级成再读一遍。
- 概念层卡住 → 回 01;原理层卡住 → 回 02 / 03;判别层卡住 → 回 04。
- 判别层是重点:它要求你在多章的方案之间做选择并说理由,这是面试真正考的。
①概念层 · 回忆(对应 01)
- namespace、group、service 三者如何共同唯一定位一个服务?cluster 参与这个定位吗?
- 临时实例和持久实例,健康分别由谁判定?各用一个词概括。
- 一个临时实例最后一次心跳之后,多少秒被标记 unhealthy、多少秒被删除?为什么分两段?
- dataId
pay-service-test.yaml拆成三段分别是什么?各对应 Spring 的哪个配置? - 服务发现和配置中心,复用了哪两层相同的隔离维度?
②原理层 · 理解(对应 02 / 03)
- Distro 里"哪个节点负责哪个服务"是怎么算出来的?写出这个表达式的含义。
- Distro 常态同步只传差异,靠的是什么机制?新节点冷启动时为什么必须先拉全量?
- 1.x 的 UDP 推 + 客户端轮询,2.x 换成了什么?最主要的两个收益是什么?
- 整个 Nacos 集群挂掉,已运行的服务为什么还能继续调用?此刻它感知不到什么?
- 配置长轮询服务端 hold 29.5s 而非 30s,这 0.5s 防的是什么?变更检测靠什么判断内容真的变了?
@Value注入的字段在配置变更后没刷新,最可能缺了什么注解?@ConfigurationProperties呢?
③应用判别层 · 迁移(综合 01–04,重点)
每题都要求你在不同章节的方案之间做选择,并说出理由——这是 capstone。
- 实例类型判别:你要把一个"网关节点"登记到 Nacos,希望它即使进程停了也保留在注册表里由运维手动管理,不被自动摘除。注册成临时还是持久实例?为什么?(综合 §1.3 + §4.1)
- 选型判别:一个 Java / Spring Cloud 新项目,既要注册中心又要配置中心,团队规模小、没有强审计权限诉求。选"一套 Nacos"还是"Eureka + Apollo"?给两条理由。(综合 §4.3)
- 发布方式判别:一个高危开关要先在少数机器验证再全量。用 Nacos 的哪种发布方式?它和普通发布在"推送对象"上差别是什么?验证期间其余实例读到的是新值还是旧值?(综合 §3.4)
- 排障判别:2.x 升级后部分客户端注册失败、日志刷连接超时,但运维说 telnet 8848 是通的。你的第一排查方向是什么?升级顺序应该服务端先还是客户端先?(综合 §2.3 + §4.4)
- 架构判别(脊柱题):需求方要求"注册中心在网络分区时仍可用、配置在任何时候强一致"。一套 Nacos 能否同时满足?把这个要求落到
ephemeral上解释。(综合 §4.1 + §4.2)
亲手画一张图
合上教程,在纸上或 Excalidraw 里画出 Nacos 的双协议分流图——只画四样东西:ephemeral 决策点、两条协议路径(AP / CP)、各自的协议名、各自的存储介质。
画完回到 图 4.1 对照:你画的图里,配置落在哪一侧?持久实例呢?两者是不是在同一侧?如果你能不看图答对这三问,这条脊柱就真的长在你脑子里了。
✓答案(全部做完再展开)
展开全部答案
① 概念层
- 唯一键 = namespace + group + service,三者全相同才是同一个服务。cluster 不参与定位,它是服务内部按机房对实例的细分。
- 临时实例:客户端(每 5s 上报心跳);持久实例:服务端(主动探活 TCP / HTTP / MySQL)。
- 15s 标记 unhealthy,30s 删除。分两段是给短暂网络抖动留缓冲:抖动恢复就回到健康,只有持续失联才彻底移除。
pay-service= prefix(默认 =spring.application.name);test= profile(spring.profiles.active);yaml= file-extension(文件格式)。- namespace 和 group——服务发现和配置中心共用同一套,所以 namespace 配错会同时导致"发现不到服务"和"读不到配置"。
② 原理层
distroHash(serviceName) % healthyNodeCount:对服务名哈希,再对健康节点数取模,落在某节点负责的索引区间,它就是该服务的 owner。所以节点数变化会让 owner 重新分配。- 常态靠每 5s 广播 checksum,对端比对后只拉差异。冷启动空数据若直接对外服务会返回空列表(比"稍旧"严重),所以先从健康对端拉全量快照再服务。
- 换成一条 gRPC 长连接。收益:① 推送可靠(不再靠 UDP + 轮询补偿);② 连接复用,单机承载约 10×。
- 消费方本地有服务列表 snapshot,服务端不可达时用它兜底继续调用。此刻感知不到任何实例的上下线(拓扑冻结在快照那一刻),新实例也无法被发现。
- 留 0.5s 网络往返余量,避免客户端先于服务端超时、把正常的"无变化"误判成请求超时。变更检测靠 MD5 比对:客户端发来持有内容的 MD5,服务端比对当前 MD5。
- 缺
@RefreshScope(要和@Value在同一个 Bean)。@ConfigurationProperties默认就支持刷新,无需额外加。
③ 应用判别层
- 持久实例(
ephemeral=false)。持久实例由服务端主动探活,失败只标记不健康、不自动删除,正好满足"停了也保留、手动管理"。临时实例会在 30s 后自动消失,不符合要求。这条直接对应那条脊柱:有固定身份的节点走 CP 侧。 - 选一套 Nacos。理由:① 注册 + 配置二合一,少维护一套中间件,契合小团队;② 原生融入 Spring Cloud Alibaba 生态,接入成本低。Eureka 2.x 已停维护、且只做注册;Apollo 治理强但在没有强审计诉求时是过度投入。(若诉求里有细粒度权限审计,则 Apollo 更合适——判别要看约束。)
- 用灰度 / beta 发布,发布时指定那几台机器的 IP。区别:普通发布推给全部订阅者,灰度只推给指定 IP。验证期间其余实例读到的仍是正式版本的旧值,因为变更没推给它们。
- 第一方向:9848 端口未放通。2.x 注册走 gRPC(主端口 +1000 = 9848),只开 8848 时 HTTP 探测看着通、gRPC 连不上。升级顺序:先服务端、后客户端(2.x 客户端连不了 1.x 服务端)。
- 能,且这正是 Nacos 的设计。AP / CP 不是全局开关,而是按
ephemeral逐条数据选:临时实例走 Distro / AP(分区时仍可注册查询,满足"注册中心高可用"),配置走 Raft / CP(多数派提交,满足"配置强一致"),两者在同一个集群同时提供。所以这两个需求不矛盾——它们从一开始就走在两条协议路径上。
学完之后
把第 16 题能讲明白,你就拿到了这份教程的核心。可以往三个方向延伸:Sentinel(流控降级,同生态)、Raft / JRaft(把 CP 这一半补到论文级)、Nacos 3.x MCP Registry(注册中心在 AI Agent 时代的新角色)。它们都挂在你已经建好的这条脊柱上。