-->
获得免费通行证,加入我们的流媒体连接-2月19日至22日; Register Now!

构建弹性API背后的秘诀

The Xumo 平台是建立在许多离散的应用程序编程接口(API)和代表性状态传输(REST)服务之上的,这些服务具有灵活性,既支持Xumo的专有内部客户端,也支持我们合作伙伴的外部客户端. 在设计API时,我们非常小心谨慎,不会对任何单一的客户端进行规定性, 而是提供一个有能力和灵活的环境,可以满足我们客户的不同实现.

The issues I address below are applicable to any online platform that is currently using or considering using a CDN provider with a web service API; I got the idea to write this article based on interactions with colleagues from other companies who were dealing with similar issues.

在开发外部API时,一个重要的方面是如何定义API和客户端之间的契约, 以及如何管理API的变更. 这种契约的改变必然会带来一定的痛苦, 所以API版本控制的话题很快就出现了. 没有API在第一次通过时是完美的,我们的也不例外.

一旦有客户端使用我们的服务,我们就承诺提供具有预期行为的服务. 即使我们的内部客户端需要修改后的响应格式,我们也必须保持对现有API的向后兼容性. 这个问题可以分为两个不同的方面. 首先是在代码库中支持多个版本的内部机制, 第二个是客户端和服务器之间的外部API契约. 这两个关注点之间有一层清晰的分离. 内部机制应该对客户端不可见(根本不可见), 因此,我们应该自由地实现任何被认为最适合手头语言和框架的方法. 它根本不应该渗透到API中.

Hypermedia API

当涉及到Xumo API的外部设计时,我们经历了一些不同的迭代. 第一个API源于采用HATEOAS或超媒体作为应用程序状态引擎. 超媒体本身就足够复杂,足以证明一篇文章的合理性, 因此,我将开门开路,强调它依赖于客户端通过单个固定端点进入API,并从收到的响应中“发现”可用的API功能, 这可能因客户而异. 典型的超媒体响应可能返回可用的百家乐软件, 以及与这些百家乐软件相关的媒体表述. 正是在这个领域,我们迎合了多个版本.

这里我们有一个API响应,表明我们可以接收版本1或版本2表示形式的百家乐软件. 如果需要,我们还可以指定XML或JSON响应. 要请求版本1的XML响应,客户端可能会发出以下请求:

Request:

Response:

服务器响应采用JavaScript对象表示法(JSON)格式, 服务器指定一个Vary:报头,这是对下游代理和浏览器缓存的指令,该响应可以根据Accept报头而变化. 如果客户端向相同的端点发出请求,但是Accept报头的值不同,那么客户端不应该使用它已经拥有的缓存响应, 因为它对于新的Accept标头请求是不正确的. So far so good. 正是Vary标头使得API版本控制中的内容协商变得麻烦. 如果您的API有多种类型的响应,并且是为缓存而设计的,那么使用Vary头充其量是不一致的. 这是一个下游指令, 用于代理和客户端, 但并不是所有的浏览器和代理都同意如何处理它. For example, 当响应中包含Vary报头时,所有版本的Internet Explorer都完全忽略最大年龄缓存报头. 浏览器将向源发出另一个请求, 即使它已经得到了正确的缓存响应!

内容交付网络(CDN)的实现在执行方式上也可能有所不同. 默认情况下,通常只考虑'Vary: Accept-Encoding'响应. 对于所有其他变量值, 默认的Edgecast行为是缓存从原点发回的第一个响应,而Akamai不会缓存任何东西(除了' Vary: Accept-Encoding'). 在edgcast情况下,您可能会遇到不确定的行为. For example, 如果CDN有机会缓存的第一个响应是版本1的百家乐软件,客户端可能会请求版本1的百家乐软件,但接收到的是版本2的百家乐软件. 即使服务器指定了“变化:接受”,CDN将完全忽略它,并表现得好像根本没有指定Vary标头.  根据您的用例,这可能被证明是一个交易破坏者.

在Akamai的案例中,可以说情况并没有那么糟糕,但这种行为仍然是不可取的. Akamai不会缓存不正确的响应, 而是每次都会回到原点. 客户端每次都能收到正确的响应, 但是原点可能会过载, 因为CDN没有缓存任何东西.

虽然可以为这些cdn创建自定义配置以获得所需的行为, 我们决定在版本控制策略中放弃内容协商. 使用一个CDN设置的任何自定义规则都会将我们绑定到该提供商,并增加切换到另一个提供商的成本——这一点不容忽视.

我们考虑的下一个版本控制方法是自定义HTTP标头.

Custom HTTP Headers

这就像是:

不幸的是,这也有许多与内容协商策略相同的缺点. 服务器需要指定“Vary: X-Api-Version”(这仍然会被下游缓存忽略),并且版本控制契约必须向客户端解释.' Like the HATEOAS, 作为集成商的内容协商方法不能简单地将请求放在浏览器中以便于测试. 结果,这种方法很快就被放弃了.

路径参数版本控制

最后一种方法是将版本信息合并到URL(查询或路径参数)中。. 我们采用了路径参数方法.

这是将显式版本添加到URL中以指定所请求的版本.g.:

http://www.server.com/api/v2/products.json?count=25&sort=price&order=desc.

As you can see, 很清楚请求的是什么版本—这是强制性的—因此客户机必须包含它(相对于基于查询参数的方法,这是一个很好的优点). 此外,如果需要,还可以在浏览器中直接使用该API.

客户端通过使用` `指定响应格式。.xml' or ‘.json’作为cdn可以处理的路径的结尾,而不需要显式或自定义配置. 它们在cdn之间完全可移植.

在撰写本文时,以下公司正在使用不同的版本控制方法:

内容协商可以完成这个任务/ Accept标头

GitHub—http://developer.github.com/v3/media/

Query Param

Amazon EC2 (API版本为YYYY-MM-DD格式)http://docs.aws.amazon.com/AWSEC2/latest/APIReference/CommonParameters.html

Azure(也支持自定义标头)http://msdn.microsoft.com/library/azure/dd894041.aspx

Path Param

Twitter—http://dev.twitter.com/rest/public

Facebook—http://developers.facebook.com/docs/apps/versions

Linked-In—http://developer.linkedin.com/docs/rest-api

PayPal—http://developer.paypal.com/docs/api/auth-headers/

About the Author

山姆·哈齐姆(Sam Hazim)是位于加州尔湾市的Xumo公司的首席服务器工程师. 致力于各类连接设备使用的服务, 山姆热衷于建立强大的, 可扩展的系统,释放其硬件的潜力. 他的核心兴趣涉及web服务、性能优化和服务安全.

Streaming Covers
Free
合资格订户
Subscribe Now Current Issue Past Issues
Related Articles

api基础知识:开发人员正在迁移到基于api的工作流

api使使用连接不同软件应用程序和平台的最佳工具变得更加容易. 他们也改变了视频开发者创造新产品的方式.

提及的公司及供应商