AWS 的 API 为何返回 XML - 从 Query API 到 REST JSON 的演进历史

解析 S3 和 EC2 的 API 返回 XML 响应的历史原因、Query API 与 REST API 的区别、从 Signature V2 到 V4 的认证方式演进,以及 SDK 所隐藏的复杂性。

2006 年的 API 设计 - XML 理所当然的时代

S3 和 EC2 于 2006 年推出时,Web API 领域中 XML 是标准数据格式。SOAP(Simple Object Access Protocol)是企业级 Web 服务的主流,通过 XML Schema 进行严格类型定义和 WSDL(Web Services Description Language)进行服务描述被视为「正确的」API 设计。JSON 虽然在 2001 年由 Douglas Crockford 提出,但到 2006 年尚未广泛普及,被评价为「轻量但缺乏类型安全性」。AWS 的早期 API 反映了这个时代的设计思想。EC2 的 API 采用「Query API」形式,在 HTTP GET 请求的查询参数中指定操作名和参数,以 XML 接收响应。例如,获取 EC2 实例列表的请求格式为 https://ec2.amazonaws.com/?Action=DescribeInstances&Version=2016-11-15。S3 的 API 采用 REST 风格,通过 HTTP 方法(GET、PUT、DELETE)和路径操作资源,但响应仍为 XML。

向后兼容性的束缚 - 为何无法废弃 XML

AWS 最重要的设计原则之一是「已发布的 API 绝不废弃」。EC2 的 Query API 从 2006 年起已持续运行近 20 年,XML 响应格式也未改变。数百万客户的应用依赖于此 API,将响应格式改为 JSON 将是大规模破坏性变更。AWS 通过在新服务中采用 JSON、同时保持旧服务 API 不变的方式解决了这个问题。2012 年以后推出的服务(DynamoDBLambdaAPI Gateway 等)几乎全部采用基于 JSON 的 REST API。DynamoDB 的 API 使用 JSON 请求/响应,Content-Type 为 application/x-amz-json-1.0。Lambda 的 API 也是基于 JSON。而 EC2、S3、SQSSNS 等早期服务至今仍返回 XML 响应。AWS SDK 在内部吸收了这种差异,开发者使用 SDK 时无需关心 XML 和 JSON 的区别。

Signature V4 - 对所有请求进行签名的机制

AWS API 的另一个特点是所有请求都需要加密签名。当前标准的 Signature Version 4(SigV4)将请求的 HTTP 方法、URL、头部和正文连接后进行哈希,使用密钥访问密钥生成 HMAC-SHA256 签名。该签名包含在 Authorization 头部中,由 AWS 端进行验证。SigV4 的签名过程由 4 个步骤组成。第一,创建规范请求(Canonical Request)。将 HTTP 方法、URI、查询字符串、头部规范化为字符串。第二,创建待签名字符串(String to Sign)。连接日期、区域、服务名和规范请求的哈希。第三,派生签名密钥。从密钥访问密钥逐步派生按日期、区域、服务的签名密钥。第四,计算签名。用签名密钥对待签名字符串进行 HMAC-SHA256 签名。手动实现这一复杂过程不现实,AWS SDK 在内部自动处理。不使用 SDK 而用 curl 调用 AWS API 时,需要自行实现这一签名过程,调试极为困难。

SDK 所隐藏的复杂性

AWS SDK 是将 API 复杂性对开发者隐藏的巨大抽象层。SDK 在内部处理的事项涵盖多个方面:请求签名(SigV4)、XML/JSON 的序列化与反序列化、重试逻辑(带指数退避)、错误处理(区分临时错误和永久错误)、分页(自动通过多次请求获取大量结果)、区域端点解析、临时凭证的自动刷新(IAM 角色的 AssumeRole)等。SDK v3(JavaScript)和 boto3(Python)将这些处理实现为中间件管道,开发者也可以添加自定义中间件。SDK 的重试逻辑尤为重要。AWS 的 API 实施限流(速率限制),短时间内发送大量请求会返回 429(Too Many Requests)错误。SDK 自动以指数退避(1 秒、2 秒、4 秒...)进行重试,开发者无需实现重试逻辑。

API 的演进与未来方向

AWS 的 API 设计在 20 年间经历了巨大演进。从早期的 Query API + XML,到 REST + JSON,再到近期的 GraphQL(AppSync)和事件驱动(EventBridge),API 范式本身在多样化。AWS API 设计中始终一贯的是「API 一旦发布就不变更」的原则。EC2 的 API 版本 2006-10-01 至今仍可运行。新功能作为新 API 版本添加,旧版本不会废弃。这种向后兼容性的维护是 AWS 可靠性的根基。企业花费数年构建的系统不会因 API 变更而突然无法运行。另一方面,这一原则也产生了技术债务。20 年前的设计决策(XML 响应、Query API 形式)至今仍在维护,新开发者会产生「为何还用这么古老的格式」的疑问。答案是「为了向后兼容性」,这体现了 AWS 将客户信任置于最优先的态度。如需系统学习 API 设计的历史与原则,专业书籍 (Amazon) 可作为参考。