1646 字
约 5 分钟
8
S02-A02 · API 与 RPC 治理:网关、契约、版本与灰度
适用读者:要对"接口改了不炸调用方"负责的人。
前置:S02-B09(HTTP 与 RPC)、S02-B10(OpenAPI 工具化)。
版本基线:OpenAPI 3.1、gRPC/protobuf 3.x、nginx/网关(示例)。
覆盖旧文:—(E 驱动)
覆盖扩展:E-S02-026(网关限流/熔断/灰度)+ 契约与版本策略。
上一篇:S02-A01 · 实时通信架构选型
下一篇:S03 · 数据结构与算法(下一系列)。
1. 一句话结论
接口治理的核心不是"写文档",而是"让契约成为唯一事实来源,并给变更设闸门"。
| 要素 | 作用 |
|---|---|
| 契约单一来源(OpenAPI / .proto 进仓库) | 服务端、客户端、文档、测试都从它生成 |
| 兼容性规则 | 规定什么能改、什么不能改 |
| 网关 | 统一鉴权、限流、路由、灰度 |
| 变更闸门 | CI 检查破坏性变更,不允许"悄悄改" |
2. 契约:从"文档"到"唯一事实来源"
| 阶段 | 表现 | 问题 |
|---|---|---|
| L0 | 接口靠口头/IM 沟通 | 每人都有一份"记忆中的契约" |
| L1 | 手写文档(Wiki) | 三天后过期 |
| L2 | 契约文件进仓库(OpenAPI/proto) | 需要 CI 校验与代码生成 |
| L3 | 契约驱动:代码从契约生成 + CI 阻断破坏性变更 | 治理闭环 |
判据:"能不能从契约自动生成客户端 SDK / 测试用例?" 能 → 你到 L2 以上了。
3. 兼容性规则表(最容易出事的地方)
3.1 HTTP/JSON
| 变更 | 兼容性 | 说明 |
|---|---|---|
| 新增可选字段 | ✅ 向后兼容 | 老客户端忽略即可 |
| 新增必填字段(请求) | ❌ 破坏 | 老客户端不传 → 服务端拒 |
| 删除字段 | ❌ 破坏 | 老客户端仍在读 |
| 字段改名 | ❌ 破坏 | 视同删除 + 新增 |
| 类型变更(int → string) | ❌ 破坏 | 反序列化失败 |
| 收紧校验(如长度上限变小) | ⚠️ 潜在破坏 | 已有合法数据可能超限 |
| 枚举新增值 | ⚠️ 视客户端实现 | 老客户端可能不认识新值 |
3.2 Protobuf(更强约束)
| 变更 | 兼容性 |
|---|---|
| 新增字段(新编号) | ✅ |
| 删除字段 | ✅ 前提:把编号 reserved,防止被复用 |
| 改字段编号 | ❌ 破坏(数据错位) |
| 改字段类型(int32 → int64) | ⚠️ 部分兼容(varint 同构可兼容,反之不行) |
| 改字段名 | ✅(proto 用编号传输) |
铁律:字段编号一旦发布就不能复用。删字段必须 reserved 5; 断掉后人复用的可能。
4. 三种破坏性变更的处置
| 处置 | 做法 | 代价 | 适用 |
|---|---|---|---|
| 并行版本 | /v2/... 或 package v2 |
维护双份、双跑期 | 大改、外部客户 |
| 兼容扩展 | 加字段 + 服务端兼容旧值 | 小 | 绝大多数场景 |
| 灰度 + 强推 | 内部服务强制升级(无外部客户) | 协调成本 | 内部 RPC、可控客户端 |
判据:调用方能不能被你强制升级? 能 → 强推;不能(浏览器、第三方)→ 并行版本。
5. 网关的职责边界
| 职责 | 放网关 | 放服务 |
|---|---|---|
| 鉴权(token 校验) | ✅ | — |
| 限流(按 key/租户) | ✅ | 精细限流需服务配合 |
| 路由与灰度(按 header/用户) | ✅ | — |
| 协议转换(REST ↔ gRPC) | ✅ | — |
| 熔断/重试 | ✅(粗粒度) | ✅(业务语义重试) |
| 业务校验 | ❌ | ✅ |
| 事务 | ❌ | ✅ |
常见错误:把业务校验放网关 → 网关变成"又一个业务系统",无法独立演进。
6. 灰度与回滚
① 契约变更 → CI 校验(破坏性变更阻断)
② 服务端先上(向后兼容版本)
③ 灰度:1% → 10% → 50% → 100%(按用户/租户/地域)
④ 观测:错误率、P99、业务成功率
⑤ 回滚:开关/路由规则切回旧版本(≤ 1 分钟)
| 判定指标 | 阈值(示例) |
|---|---|
| 5xx 率 | 上升 > 0.5 个百分点 → 回滚 |
| P99 延迟 | 上升 > 30% → 回滚 |
| 业务成功率 | 下降 > 1% → 回滚 |
顺序铁律:先上服务端,后上客户端(服务端兼容旧客户端;反过来必炸)。
7. 观测与契约漂移检测
| 检查 | 手段 |
|---|---|
| 实现是否符合契约 | 契约测试(schemathesis / Dredd) |
| 是否存在未文档化字段 | 抓包对比契约(漂移检测) |
| 客户端是否用了未定义字段 | 网关日志字段级统计 |
| 版本使用分布 | 按 Accept-Version 统计(决定旧版本下线时间) |
8. 交付物
| 交付物 | 内容 |
|---|---|
| 契约仓库结构 | api/openapi/*.yaml 或 proto/,含 CI 校验 |
| 兼容性检查 | 工具配置(如 openapi-diff、buf breaking) |
| 版本演进表 | 版本 / 状态(active/deprecated/retired)/ 下线计划 |
| 灰度方案 | 分组规则、观测指标、回滚开关位置 |
| ADR | 为何用并行版本而非兼容扩展(或反之) |
9. 自测(架构师版)
- 为什么"新增必填字段"是破坏性变更,而"新增可选字段"不是?
- Protobuf 删字段为什么必须
reserved? - 什么情况下可以"强推"而不是并行版本?
- 网关为什么不该做业务校验与事务?
- 灰度时你最先看哪个指标?为什么不是"平均延迟"?
10. 系列收尾
S02 到此结束(16 篇)。下一系列 S03 · 数据结构与算法(186 张旧卡),从复杂度与基础结构开始,承接 B02/B04 的"进程与可靠传输"之后所需的算法基础。
S02 的验收报告见 ../acceptance.md。
本篇属于系列《S02 · 计算机与网络基础》,架构师层第 2 篇。扩展点 E-S02-026。
S02-A02 · API 与 RPC 治理:网关、契约、版本与灰度
https://www.clxhxhhr.top/posts/5196/ 评论
0 条
还没有评论,先写一条吧。