直接兼容性
什么是直接兼容性
直接兼容性(前向兼容性)是系统能够正确处理比最初设计的新客户端或数据的能力。简而言之:当新客户端到达时,旧服务器不会崩溃;老消费者在遇到新信息时不会倒下。
从向后兼容(当新系统支持旧客户时),前进的方向有所不同:我们设计协议和客户以"生存"未来的扩展,而无需对整个生态系统进行全面升级。
基本原则
1.Tolerant reader & tolerant writer
读者忽略未知字段/标题,并允许具有正确后退的新的enum值。
Writer不会发送服务器未明确声明为受支持的任何内容(capabilities)。
2.Capability negotiation
在handshake阶段显式交换功能(fichi/版本/媒体类型)。客户端会根据服务器响应调整其行为。
3.默认降解
新功能被认为是可选的:如果服务器/用户不支持它们,则脚本仍将以有用的最小值(MGC)结尾。
4.稳定核心(MGC)
最低保修合同不变;创新作为扩展而存在。
5.错误合同作为协议的一部分
可预测的代码/原因("不支持","媒体类型未知")允许客户端自动回滚到受支持的模式。
6.没有惊喜的版本
主要生产线是分开的;次要扩展不需要服务器/用户更新。
这在哪里尤为重要
具有长寿命集成的公共API(合作伙伴,移动应用程序中的SDK)。
具有多个独立用户的活动平台。
移动客户端更新速度比后端慢。
Edge/IoT,其中一些设备队很少通过。
样式的实现模式
REST/HTTP
Negotiation:
带参数的"接受"/介质('application/vnd。example.order+json;v=1;profile=risk`).
"Prefer: include=……"用于可选单元。
标题"X-Capabilities: risk_score,item_details_v2'。
- 仅当服务器确认了能力时(通过OPTIONS/DESC/LID-ENPOINT),才以基本格式发送请求,扩展。
- "415/406/501"会自动回滚到支持的格式/方法。
- 服务器响应:未知参数-忽略;多余的字段-允许;错误格式("type/code/detail/trace_id")是稳定的。
gRPC / Protobuf
稳定服务:新方法/领域-加法;旧服务器静静地忽略未知的查询字段。
功能发现:"GetCapabilities()"方法返回幻影/极限列表。除非服务器已声明,否则客户端不会调用"v2方法"。
流媒体:记录最少信息集的顺序;新的"框架"标记旧客户端忽略的扩展/类型。
GraphQL
前向友好:服务器上会出现新的字段/类型-旧客户端根本不要求它们。
禁止猜测:客户必须保留电路(内窥镜/密码根),并且不得发送未知的指令/变量。
降级:如果服务器不了解自定义指令/功能-客户端将构建没有它的请求。
Event-driven (Kafka/NATS/Pulsar, Avro/JSON/Proto)
注册表中方案的FORWARD兼容性:旧用户可以读取新方案记录的消息。
带有默认值的加法字段:新生产商不会打破旧用户。
Core vs Enriched:内核保持不变,新信息发布在".enriched"或作为可选字段。
设计实践
1.最低要求合同(MGC)
该操作必须具有"狭窄的颈部",所有服务器将支持多年。
2.Ficha-Flag在合同级别
将fici描述为命名功能:"risk_score","pricing_v2","strong_idempotency"。客户端明确打开它们。
3."不支持"的显式错误代码"
HTTP: `501 Not Implemented`, `415 Unsupported Media Type`, детальные `problem+json`.
gRPC: `UNIMPLEMENTED`/`FAILED_PRECONDITION`.
事件:带有"reason=unsupported_feature"的DLQ中的路由。
4.不依赖顺序/完整列表
客户端必须为新的enum值,缺少新字段以及"附加"属性做好准备。
5.稳定的ID和格式
不要改变行内的ID/分期付款密钥格式-这打破了读者一侧的前进。
6."机器可读"文档"
主机描述符:OpenAPI/AsyncAPI/Proto descriptors/GraphQL SDL。客户可以验证相片支持。
前向兼容性测试
FORWARD/FULL模式下的Schema-diff:新方案验证旧消费者/服务器。
客户端合同测试:新客户机对旧服务器执行开机/关机。
Golden requests:在"旧"服务器上运行一组"新"请求;预计会退化而不会出现重大错误。
Chaos/latency:检查定时器/转发器-新客户端必须正确地体验旧服务器最坏的SLA。
金丝雀:一些新客户使用以前的服务器版本-收集错误/降级遥测。
可观察性和操作指标
不支持快照及其自动回滚的查询/消息的百分比。
按客户端版本分配(User-Agent/元数据/claims)。
错误"UNIMPLEMENTED/501/415"以及带有"unsupported_feature"的DLQ中的路由。
降解时间:MGC对"扩展"响应的p95/p99。
方桉注册表中的兼容模式
FORWARD:新条目与旧读者兼容(需要默认、可选)。
FULL: и FORWARD, и BACKWARD;方便公共合同。
建议:对于事件-制片人的BACKWARD和消费者的FORWARD(通过tolerant reader),对于外部API-FULL。
示例
REST (capabilities+降解)
1.客户端执行"GET/meta/capabilities" →"{"risk_score":false,"price_v2":true}"。
2.在"POST/orders"上发送基字段;"risk_score"不提示,因为服务器无法访问它。
3.如果不小心发送了"Prefer: include=risk_score",则服务器将在没有"risk_score"(或"Preference-Applied: none")字段的情况下响应200-客户端不会掉落。
gRPC (discovery)
"GetCapabilities()"返回方法/幻想列表。如果不调用"CaptureV2",则客户端不会调用"CaptureV2"-而是使用"Capture"并将输入本地转换为受支持的视图。
事件(注册表中的FORWARD)
制作人添加了"risk_score"字段(带有默认功能的不可读性)。老主人忽略了他。它的逻辑只使用稳定的内核字段。
反模式
硬客户端:通过惠特利斯特字段过滤响应,落在陌生的属性上。
隐式fichi:客户端开始发送新参数,而无需检查大写字母。
更改线路内的ID/密钥格式 →旧服务器/用户停止理解新的请求/消息。
关于完整的enum列表(switch undefault)的加密假设。
编译为流控制:将错误字符串替换为合同代码。
实施支票
- 由MGC定义;新功能被标记为可选功能。
- 描述并实现了能力要求(端口/元数据/手写)。
- 客户忽略不熟悉的字段并正确处理新的enum (fallback)。
- 错误合同可预见"不支持"(HTTP/gRPC/Event)。
- 已将电路注册表配置为FORWARD/FULL以匹配工件。
- 自动测试:schema-diff (FORWARD),客户端针对旧服务器的合同测试,金丝雀。
- 度量标准:客户版本,幻灯片故障,降解比例,p95 MGC。
- Documents/SDK发布幻灯片列表和退化示例。
FAQ
在实践中,前进与后退有什么不同?
Backward:新服务器不会破坏旧客户端。前进:旧服务器不会中断新客户端(或旧用户端-来自新消息)。理想情况下,你能完全实现。
你是否总是需要输入大写字母?
如果您期望在没有同步发布的情况下进行积极的演变-是的。这比保持数十条主要生产线便宜。
如何与安全?
新的fici必须需要单独的scopes/claims。如果服务器不支持它们,则客户端不应降低安全性,而应放弃fichi。
可以根据服务器版本"猜测"支持吗?
不希望。最好明确查询(capabilities)或查看介质/方案。
底线
直接互操作性是谈判能力和安全退化的纪律。稳定的内核、能力限制、可加性扩展和可预测的错误使新客户和数据能够与旧服务器和消费者相处,而无需大量发布和夜间迁移。