配置世代与发布
实体是双态的:draft 与 published
每个配置实体(route/cluster/orch/listener…)在同一键空间里同时存在两个世代段:
| 段 | 含义 | 谁在用 |
|---|---|---|
| draft | 可改的候选态 | 管理者——写多少次都不影响线上 |
| published | 服务中的现行态 | 数据面——只读这一段 |
- 写命令(
config set)只写 draft——没有热改旁路,一切生效都经过发布; - 发布=把 draft 全集编译后翻转成新 published(世代切换+热装载,不停机);
- 删除保留双段语义(draft+published 一起删,或指定段)。
发布=七阶段流水线
①Validate → ②Resolve → ③Plan → ④Compile(干跑)→ ⑤Stage → ⑥Publish → ⑦Rollback(备用)
| 阶段 | 做什么 | 失败语义 |
|---|---|---|
| ① Validate | 实体级纯函数校验(结构化 issues:哪个实体哪个字段什么问题) | 422+issues 清单 |
| ② Resolve | 引用闭合(route→cluster→发现源…)+外部资源解析 | 422+悬空引用定位 |
| ③ Plan | 编译计划与受影响路由集 | 422 |
| ④ Compile 干跑 | 对「将要生效态」完整编译——编不过=发布拒绝,旧表续服 | 422+编译错误(旧世代不受影响) |
| ⑤ Stage | 产物落 Blob 域、指针就绪 | 可重试 |
| ⑥ Publish | published 翻转+generation 写入+历史链记录 | 原子提交 |
| ⑦ Rollback | 翻回上一(或指定)世代——重放历史快照 | 随时可执行 |
两个关键性质:
- 编译是确定性纯函数:同世代配置+同编译器版本 ⇒ 产物逐字节等价——产物可再生, 不需要备份;历史链记录每个世代的完整快照引用,是回滚的依据。
- 干跑即④:
publish dry-run走 ①②③④(零副作用),回执候选世代号与错误清单;publish go全量执行。配置错误永远不会污染线上流量。
KV 与 Blob 双域:raft 只复制指针
| 域 | 存什么 | 特点 |
|---|---|---|
| KV | 指针与元数据(实体地址、generation、产物指针) | raft 复制——小而频繁 |
| Blob | 数据体(编译产物段、插件包等) | 按需物料化——大而不常变 |
raft 复制 KV 指针;各节点拿到指针后从 Blob 域物料化产物。大数据体(如 4MB 级产物) 不膨胀 raft 日志——指针模式下大产物与小产物花差不多的日志条目。
版本戳
- generation:租户级世代号,每次发布递增(
publish status可查当前值); - logicalAddress:每次实体写入返回的地址指纹(hex32)——「写没写成功、写的是哪一版」的凭据;
- rev CAS:乐观并发——并发写同一实体时后写者基于 rev 检测冲突。