Chapter 05

自测题库

前四章从概念建到原理再到选型。这一章不教新东西——它逼你回忆和判别。 三层梯度共 16 题,最后一层是跨章场景题,能答上才算把那条脊柱真正内化了。

怎么用这一章

  • 所有答案集中在页面最底部的一个折叠块里——先把全部题做完再展开,中途偷看等于把自测降级成再读一遍。
  • 概念层卡住 → 回 01;原理层卡住 → 回 02 / 03;判别层卡住 → 回 04。
  • 判别层是重点:它要求你在多章的方案之间做选择并说理由,这是面试真正考的。
应用判别 原理层 · 理解 对应 02 / 03 概念层 · 回忆 对应 01 难度 ↑
图 5.1三层梯度:概念回忆(01)打底,原理理解(02 / 03)居中,应用判别(综合 01–04)封顶。 注意:顶层最窄也最难——它不问"是什么",问"这个场景你选哪个、为什么"。能稳定答对顶层,才说明 schema 建成了。

①概念层 · 回忆(对应 01)

  1. namespace、group、service 三者如何共同唯一定位一个服务?cluster 参与这个定位吗?
  2. 临时实例和持久实例,健康分别由谁判定?各用一个词概括。
  3. 一个临时实例最后一次心跳之后,多少秒被标记 unhealthy、多少秒被删除?为什么分两段?
  4. dataId pay-service-test.yaml 拆成三段分别是什么?各对应 Spring 的哪个配置?
  5. 服务发现和配置中心,复用了哪两层相同的隔离维度?

②原理层 · 理解(对应 02 / 03)

  1. Distro 里"哪个节点负责哪个服务"是怎么算出来的?写出这个表达式的含义。
  2. Distro 常态同步只传差异,靠的是什么机制?新节点冷启动时为什么必须先拉全量?
  3. 1.x 的 UDP 推 + 客户端轮询,2.x 换成了什么?最主要的两个收益是什么?
  4. 整个 Nacos 集群挂掉,已运行的服务为什么还能继续调用?此刻它感知不到什么?
  5. 配置长轮询服务端 hold 29.5s 而非 30s,这 0.5s 防的是什么?变更检测靠什么判断内容真的变了?
  6. @Value 注入的字段在配置变更后没刷新,最可能缺了什么注解?@ConfigurationProperties 呢?

③应用判别层 · 迁移(综合 01–04,重点)

每题都要求你在不同章节的方案之间做选择,并说出理由——这是 capstone。

  1. 实例类型判别:你要把一个"网关节点"登记到 Nacos,希望它即使进程停了也保留在注册表里由运维手动管理,不被自动摘除。注册成临时还是持久实例?为什么?(综合 §1.3 + §4.1)
  2. 选型判别:一个 Java / Spring Cloud 新项目,既要注册中心又要配置中心,团队规模小、没有强审计权限诉求。选"一套 Nacos"还是"Eureka + Apollo"?给两条理由。(综合 §4.3)
  3. 发布方式判别:一个高危开关要先在少数机器验证再全量。用 Nacos 的哪种发布方式?它和普通发布在"推送对象"上差别是什么?验证期间其余实例读到的是新值还是旧值?(综合 §3.4)
  4. 排障判别:2.x 升级后部分客户端注册失败、日志刷连接超时,但运维说 telnet 8848 是通的。你的第一排查方向是什么?升级顺序应该服务端先还是客户端先?(综合 §2.3 + §4.4)
  5. 架构判别(脊柱题):需求方要求"注册中心在网络分区时仍可用、配置在任何时候强一致"。一套 Nacos 能否同时满足?把这个要求落到 ephemeral 上解释。(综合 §4.1 + §4.2)
亲手画一张图

合上教程,在纸上或 Excalidraw 里画出 Nacos 的双协议分流图——只画四样东西:ephemeral 决策点、两条协议路径(AP / CP)、各自的协议名、各自的存储介质。 画完回到 图 4.1 对照:你画的图里,配置落在哪一侧?持久实例呢?两者是不是在同一侧?如果你能不看图答对这三问,这条脊柱就真的长在你脑子里了。

✓答案(全部做完再展开)

展开全部答案

① 概念层

  1. 唯一键 = namespace + group + service,三者全相同才是同一个服务。cluster 不参与定位,它是服务内部按机房对实例的细分。
  2. 临时实例:客户端(每 5s 上报心跳);持久实例:服务端(主动探活 TCP / HTTP / MySQL)。
  3. 15s 标记 unhealthy,30s 删除。分两段是给短暂网络抖动留缓冲:抖动恢复就回到健康,只有持续失联才彻底移除。
  4. pay-service = prefix(默认 = spring.application.name);test = profile(spring.profiles.active);yaml = file-extension(文件格式)。
  5. namespace 和 group——服务发现和配置中心共用同一套,所以 namespace 配错会同时导致"发现不到服务"和"读不到配置"。

② 原理层

  1. distroHash(serviceName) % healthyNodeCount:对服务名哈希,再对健康节点数取模,落在某节点负责的索引区间,它就是该服务的 owner。所以节点数变化会让 owner 重新分配。
  2. 常态靠每 5s 广播 checksum,对端比对后只拉差异。冷启动空数据若直接对外服务会返回空列表(比"稍旧"严重),所以先从健康对端拉全量快照再服务。
  3. 换成一条 gRPC 长连接。收益:① 推送可靠(不再靠 UDP + 轮询补偿);② 连接复用,单机承载约 10×。
  4. 消费方本地有服务列表 snapshot,服务端不可达时用它兜底继续调用。此刻感知不到任何实例的上下线(拓扑冻结在快照那一刻),新实例也无法被发现。
  5. 留 0.5s 网络往返余量,避免客户端先于服务端超时、把正常的"无变化"误判成请求超时。变更检测靠 MD5 比对:客户端发来持有内容的 MD5,服务端比对当前 MD5。
  6. 缺 @RefreshScope(要和 @Value 在同一个 Bean)。@ConfigurationProperties 默认就支持刷新,无需额外加。

③ 应用判别层

  1. 持久实例(ephemeral=false)。持久实例由服务端主动探活,失败只标记不健康、不自动删除,正好满足"停了也保留、手动管理"。临时实例会在 30s 后自动消失,不符合要求。这条直接对应那条脊柱:有固定身份的节点走 CP 侧。
  2. 选一套 Nacos。理由:① 注册 + 配置二合一,少维护一套中间件,契合小团队;② 原生融入 Spring Cloud Alibaba 生态,接入成本低。Eureka 2.x 已停维护、且只做注册;Apollo 治理强但在没有强审计诉求时是过度投入。(若诉求里有细粒度权限审计,则 Apollo 更合适——判别要看约束。)
  3. 用灰度 / beta 发布,发布时指定那几台机器的 IP。区别:普通发布推给全部订阅者,灰度只推给指定 IP。验证期间其余实例读到的仍是正式版本的旧值,因为变更没推给它们。
  4. 第一方向:9848 端口未放通。2.x 注册走 gRPC(主端口 +1000 = 9848),只开 8848 时 HTTP 探测看着通、gRPC 连不上。升级顺序:先服务端、后客户端(2.x 客户端连不了 1.x 服务端)。
  5. 能,且这正是 Nacos 的设计。AP / CP 不是全局开关,而是按 ephemeral 逐条数据选:临时实例走 Distro / AP(分区时仍可注册查询,满足"注册中心高可用"),配置走 Raft / CP(多数派提交,满足"配置强一致"),两者在同一个集群同时提供。所以这两个需求不矛盾——它们从一开始就走在两条协议路径上。
学完之后

把第 16 题能讲明白,你就拿到了这份教程的核心。可以往三个方向延伸:Sentinel(流控降级,同生态)、Raft / JRaft(把 CP 这一半补到论文级)、Nacos 3.x MCP Registry(注册中心在 AI Agent 时代的新角色)。它们都挂在你已经建好的这条脊柱上。