![90276478ce86d7296b55799e43a36bb9.png](https://i-blog.csdnimg.cn/blog_migrate/63c4459032486e3d8bf656709ef5ac03.jpeg)
最近几年, 很多种API范例涌现出来,目前比较流行的标准如REST, RPC, GraphQL, WebHooks 以及WebSockets等。但是大家大家真的对每一种都很了解吗?什么场景下适合用哪种API范例,以及他们的分别的优缺点都是什么呢?
最近参与到组里重构接口,所以深入的学习了一下如何写出一个好的API。那么什么是一个好的API呢?我非常赞同一位uber资深专家的观点:
“一个好的API可以归结为您试图解决的问题以及解决问题的价值。如果您要访问唯一的数据集或应用非常复杂的功能,那么您可能会愿意使用一些令人困惑的、不一致的、缺乏文档的APIs。否则,好的APIs倾向于提供清晰性(目的、设计和上下文)、灵活性(适应不同场景的能力)、强大性(提供的解决方案的完整性)、可编程性(通过迭代和实验快速学习的能力)以及文档化。”
那么一个好的API一定离不开好的设计范例,在业界常见的API范例主要分为两种类型:请求响应 (Request-Response) APIs 和 事件驱动 (Event-Driven) APIs。
今天这篇文章会给大家分享一些常见的Event-Driven APIs范例都有哪些,以及他们的应用场景和优缺点,希望可以帮助到不知如何选择API范例的同学们!
Event-Driven APIs (事件驱动 APIs)
大家可能都听过REST API, 使用像REST这种请求-响应 类型的API 在有一种场景下很不友好:当对于数据不断变化的服务,使用请求-响应api,响应可能很快就会过时。要想跟上数据的变化,开发人员通常需要不断轮询API。在这种情况下,如果使用请求响应类型的API, 那么开发人员就会经常以固定的频率去查询API端点从而来判断是否有新的数据。
那么开发人员在这种场景下应该以什么样的频率去请求数据呢?这就是一个很难解决的问题。如果开发人员以较低的频率去请求数据,他们的应用程序很可能没有关于自上次轮询以来发生的所有事件的数据(比如创建、更新或删除的资源)。如果不想错失数据的话可以增加轮询的频率,但是,频繁的轮询又会导致大量资源浪费,因为大多数API调用不会返回任何新数据。Zapier在之前做了一项研究,发现只有大约1.5%的API调用返回了新数据。
为了解决实时共享事件的数据,我们从而有了事件驱动类型的API范例,今天我们介绍三种常见的机制:WebHooks, WebSockets, 以及 HTTP Streaming.
先让我们概括的看一下这三者的应用的场景以及优缺点,之后我会对每一种展开详细的介绍
![21741b1ad1d5233761b35aa73c5297ad.png](https://i-blog.csdnimg.cn/blog_migrate/de19f32d684115277145cdcf928974c3.jpeg)
WebHooks
WebHook本质上可以理解为一个接受HTTP POST(或GET、PUT、DELETE)的URL。实现webhook的API提供者只会在有事情发生时向配置的URL发布一条消息。与请求-响应APIs不同,webhook可以实时接收更新。一些API提供商,如Slack、Stripe、GitHub和Zapier,都支持WebHooks。例如,如果你想用Slack的Web API跟踪Slack团队中的“channel”,你可能需要不断地在API中按一定频率轮询新的channel。然而,如下图所示,通过配置WebHook,您可以在创建channel时自动接收通知。
![84d5218c5d542a17e38642326bf647e0.png](https://i-blog.csdnimg.cn/blog_migrate/5a60092a045dff45cc630f9428722a6f.jpeg)
(Polling versus WebHooks)
因此,我们发现WebHooks非常适合在服务器之间轻松地共享实时数据。从程序开发人员的角度来看,实现WebHooks通常很容易,因为它只需要创建一个新的HTTP endpoint来接收事件。这意味着他们通常可以重用现有的代码结构。
但是与此同时,支持WebHooks同样需要克服一些困难:
1. Failures and retries:
为了确保WebHooks被成功的传递,建立一个系统来重试WebHooks传递是很重要的。例如,Slack公司构建了一个系统,它最多允许重试三次失败:一次是立即重试,一次是一分钟后重试,最后一次是五分钟后重试。此外,如果端点仍然有95%的请求返回错误,Slack就会停止向WebHooks端点发送事件并通知开发者 。
2. Security
对于WebHooks,开发人员必须要确保他们收到了一个合法的WebHooks。很多开发人员使用未经验证的WebHooks从而导致了很多安全问题。因此很多API提供者都需要遵循一些常见的模式来保护WebHooks,具体的安全模式将在之后的API security文章中具体阐述。
3. Firewalls
运行在防火墙后的应用程序可以通过HTTP访问APIs,但它们无法接收入站流量。对于这样的应用,想利用WebHooks是困难的,通常是不可能的。
4. Noise
通常来说,每个WebHook调用代表一个单独的事件。当在短时间内发生数千个事件,我们需要通过一个WebHooks发送时,将有可能会产生很多的noise.
WebSockets
WebSocket是一个协议,通过传输控制协议(TCP)连接来建立一个双向流通信通道。虽然该协议通常在web客户端(例如浏览器)和服务器之间使用,但有时也用于服务器与服务器之间的通信。
WebSocket协议被大部分主流浏览器支持,并且经常被实时的应用程序使用。例如,Slack公司使用WebSockets将workspace中发生的各种事件发送给clients:包括新消息、添加到项目中的表情和创建的channel等。Slack还为开发者提供了基于WebSockets的实时消息API,这样他们就可以实时接收来自Slack的事件和发送消息。与之类似,Trello公司使用WebSocket将其他人所做的更改从服务器推送到正在监听相应通道的浏览器上。
WebSockets可以在低开销下启用全双工通信(server和client可以同时通信)。此外,它们被设计在80或443端口上工作,这使得它们能够很好地和可能阻塞其他端口的防火墙一起工作。对于企业开发人员来说,这是一个特别重要的考虑因素。例如,一些使用Slack API的企业开发者更喜欢使用WebSocket API而不是WebHook,因为他们可以安全地从Slack API接收事件,而不需要打开一个HTTP WebHook端点到互联网上发布消息。
WebSockets非常适合快速、实时的流数据和长时间的连接。但是,如果您计划在移动设备上或在连接不稳定的地区提供这些服务,那么请一定要小心。客户端应该保持连接处于活动状态。如果连接一旦终止,那么客户端需要重新启动它。
WebSockets还存在可伸缩性 (scalability) 相关的问题。使用Slack的WebSocket API的开发者必须为每个使用他们的应用的团队建立连接。这意味着,如果一个应用程序安装在10,000个Slack workspace上,开发人员将负责维护Slack服务器和应用程序服务器之间的10,000个连接。
HTTP Streaming
当使用HTTP请求-响应的APIs时,客户端给服务器发送HTTP请求,服务器可以返回有限长度的HTTP响应。那么当这个响应的长度不确定的时候我们应该怎么办呢? 这时候就可以使用HTTP Streaming,服务器可以持续的给单个长时间连接的客户端推送新数据。
![c7894d041427012f5605a83d244f555d.png](https://i-blog.csdnimg.cn/blog_migrate/8648c7a4eaabb23854f478e2514e446a.jpeg)
(Client–server interaction with an HTTP Streaming API)
要通过持久连接从server传输数据到client,有两种方法。第一个方法是服务器将传输编码header设置为多块的(chunked)。这向客户端表明,数据将以新行分隔的字符串块的形式到达。对于开发人员来说,这是很容易解析的。另一个方法是是通过服务器发送事件(Server-sent event)进行传输流数据。这个方法非常适合在客户端浏览器中使用,因为它们可以使用标准化的EventSource API。
Twitter利用HTTP Streaming协议,通过在app和Twitter's Streaming APIs之间打开的单个连接来传递数据。对于开发人员来说,最大的好处是他们不需要持续地对Twitter API进行轮询以获取新的推特。Twitter的Streaming API's可以通过单个HTTP连接而不是自定义协议推送新的推特,这因此为Twitter和他们的开发人员节省了大量的资源。
虽然HTTP流很容易使用,但也存在一个与缓冲有关的问题。客户端和代理通常有缓冲区限制。在达到阈值之前,它们可能不会开始向app渲染数据。此外,如果客户端想要频繁地更改监听的事件,那么HTTP Streaming并不是理想,因为它需要重新连接,导致增加额外的开销。
总结
这篇文章中我们讨论了基于事件驱动类型的API范例,以及他们分别适用于哪些场景。当我们为一款产品设计API的时候,应该充分总结出主要的需求和使用场景,从而选择一种或者多种合适的API范例。例如,Slack API支持多种APIs:WebSockets, WebHooks 以及 RPC-style。
在选择API范例时的时候,不存在一种万能的解决方案。所以在选择之前一定仔细思考哪种解决方案最适合你的客户,哪种解决方案能帮助你实现业务目标,以及哪些限制是你的服务可以容忍的。
“预告”
下一篇中将会继续为大家分享常见的Request-Response APIs,大家喜欢的话可以继续关注!
往期API设计文章
Justin:【API设计系列】GraphQL | 一种为你的API 而生的查询语言
Justin:【设计API系列】RPC | 以下是你要掌握的远程过程调用 (RPC)
Justin:【设计API系列】你真的清晰的了解过REST APIs么?奶茶的故事让你再也不会忘记它
Justin:【设计API系列】一文了解常见的事件驱动APIs范例