19.2 OpenAPI、gRPC、AsyncAPI 与契约演进
契约把路径、消息、字段、错误和兼容承诺变成可评审、可生成、可测试的制品。它不是实现自动导出的漂亮文档,而是生产者和消费者共同依赖的边界。
选择契约形式
| 场景 | 常见契约 | 关注点 |
|---|---|---|
| HTTP 请求/响应 | OpenAPI | 路径、方法、参数、schema、安全和响应 |
| 高效服务 RPC/流 | Protocol Buffers + gRPC | 方法、消息字段号、deadline、状态与流语义 |
| 消息与事件 API | AsyncAPI | channel、operation、message、协议 binding 与 schema |
协议选择取决于客户端生态、浏览器需求、流式交互、性能、治理和长期兼容,不存在对所有边界最优的一种协议。
OpenAPI 描述 HTTP 契约
openapi: 3.2.0
info:
title: Tournament API
version: 1.4.0
paths:
/tournaments/{id}:
get:
operationId: getTournament
parameters:
- name: id
in: path
required: true
schema: { type: string, format: uuid }
responses:
'200':
description: Tournament found
'404':
description: Tournament not found契约应在评审和 CI 中检查:唯一 operationId、认证声明、所有状态响应、分页与幂等约定、示例是否通过 schema 校验。
生成客户端能减少手写错误,但生成代码不能替代语义设计。SDK 还要处理重试、deadline、认证、可观测性和版本支持政策。
gRPC 契约保护字段号
service ScoringService {
rpc SettleMatch(SettleMatchRequest) returns (SettleMatchResponse);
}
message SettleMatchRequest {
string match_id = 1;
string winner_id = 2;
string idempotency_key = 3;
}Protocol Buffers 的字段号是线上身份。删除字段后应 reserved 原编号和名称,不能把编号分配给新语义:
message SettleMatchRequest {
reserved 2;
reserved "winner_id";
string match_id = 1;
string idempotency_key = 3;
}客户端应显式设置 deadline。DEADLINE_EXCEEDED 对写请求仍可能表示服务端已完成,必须结合幂等键或状态查询处理。
gRPC status code 应区分参数无效、前置条件失败、并发冲突、未认证、无权限和暂时不可用;不要把所有异常映射为 UNKNOWN 或 INTERNAL。
AsyncAPI 描述消息交互
消息契约不只包含 payload,还应说明:
- channel/topic 与发布、订阅操作;
- 事件 ID、聚合 ID、版本和时间字段;
- 分区键与顺序范围;
- schema 兼容策略;
- 安全、协议 binding 和重试/死信约定;
- 生产者和消费者所有者。
AsyncAPI 能描述结构,端到端投递、幂等和补偿仍需运行设计与测试。
“新增字段”也可能破坏消费者
结构上向后兼容的变更可能语义不兼容:
- 新增枚举值会击穿客户端的穷举分支;
- 原可选字段变成业务必填;
- 数字单位从秒变毫秒;
- 列表排序规则改变;
- 以前不会为空的数组开始返回空;
- 错误码含义或重试建议改变。
兼容性要同时检查 wire、source、behavior 和 data 四个层面。
版本策略
优先做兼容演进:新增可选能力、维持旧语义、给出弃用窗口。只有无法兼容时才引入新主版本或新资源。
版本可以放在路径、header、media type 或 schema/topic 名中。选择哪种不如以下问题重要:
- 两个版本要并存多久;
- 客户端如何发现弃用和迁移指南;
- 生产者如何知道还有谁使用旧版;
- 何时停止支持,谁批准;
- 回滚时新旧数据是否兼容。
契约测试的三层门禁
- 静态兼容检查:OpenAPI/Proto/AsyncAPI diff 和 lint;
- 提供者验证:实现是否满足契约和示例;
- 消费者场景:关键消费者依赖的字段与交互是否仍成立。
消费者驱动契约适合捕捉真实依赖,但不能让每个消费者冻结提供者的内部设计。契约应围绕公开行为,避免断言无关字段和调用次数。
治理不是中央审批队列
有效治理提供自动化 paved road:模板、lint、兼容 diff、生成、测试、目录和弃用仪表盘。平台团队制定共通安全与可操作性规则,领域团队仍拥有业务语义。
每个契约都需要:所有者、稳定级别、认证方式、SLO、变更记录、弃用政策和支持渠道。
参考资料
- OpenAPI Initiative, OpenAPI Specification
- gRPC, Core concepts
- gRPC, Status codes
- AsyncAPI Initiative, AsyncAPI Specification