API、WebSocket和Webhook
起因
最近在做一个微信公众号的后端服务,希望可以调用chatgpt的api实现3.5的交互回答。
整个过程涉及三个服务器的交互:
- 微信官方的服务器(用于接受用户消息,post给公众号后端),
- 公众号后端服务器(接受用户消息并post给一个可以请求openai的api的服务器获得chatgpt响应的回答),
- 远程可以发起chatgpt请求的服务器。
其中三个服务器的消息逻辑处理和各自的token认证我已经完成了,现在需要的就是三者之间的通信方式如何选择。微信的服务器和后端是通过https的,即api通信,而发起chatgpt请求还没有决定。
有这个考虑主要在之前搭建tgbot的时候使用了webhook的方式实现实时通讯。现在类比到微信公众号进行chatgpt的响应的后端搭建,我以为应该需要一个持久的连接,并保持上下文的联系。但是通过查阅资料发现,仍然使用api通信就可以了,因为这个通讯过程不涉及多人聊天,服务器不会驻留消息希望发送给客户端。只需要单向通讯就就可以完成了。
探索
Web 应用中,我们需要在浏览器和服务器之间进行通信;有时,服务器需要将消息返回浏览器;此外,在某些情况下,后端服务还可能依赖于另一个需要很长响应时间的服务。
这就是 API、WebSockets 和 WebHooks 发挥作用的地方。它们为该问题提供了完美的解决思路,让我们得以在应用的不同模块之间进行通信和数据同步。
API
大多数情况下,API 通信使用 JSON 或 XML 作为传输数据的格式。
让我们假设一个场景 —— 用户在电商网站上搜索商品。一旦用户使用搜索查询请求了自己想要查找的商品,他就会在几秒钟内得到响应。API 的工作方式就是如此简单
但是,使用 API 的时候,除非浏览器定期发送请求检查更新情况,否则没有一种直接的方法可以让服务器主动与浏览器进行通信。如果在一个通信聊天后端中,这将会使用长轮询的方式不断询问服务器:有消息吗?有消息吗?有消息吗?来接受服务器收到的消息,这对于实时通信显然是低效的,并且不断的轮训会消耗很多无效的服务器资源。
重点:单向通信。
WebSockets
WebSockets 允许用户和服务商之间建立一个持久的双向通信来解决这个问题。
WebSockets为实时通信提供了较好的解决方案,使用全双工信道可以让服务器随时向用户发送消息。
在上述的实时聊天例子中,ws在客户端和服务端建立一个持久的双向连接,用户可以发送消息给服务器,服务器接受到其他用户发送给该用户的消息也可以发送给该用户。这对于实时通讯来说是个不错的方案。但是ws的消息格式比api更复杂,速度不如api响应。
另一方面,一直保持连接打开会消耗资源、影响能耗(移动设备),并且难以扩展服务。使用 WebSockets 进行实时通信是不错的选择,但对于移动设备来说不是最佳方案。
此外,如果我们的后端是依赖于外部服务来生成报告的,那么 WebSockets 同样不是后端与外部服务通信的最佳选择。
重点:双向通信。
WebHooks
WebHooks 这类机制在这里就派上用场了。WebHooks 通过提供一种断开机制以接收来自服务商的响应,从而为 WebSockets 中的难题提供了解决方案。
用户将 WebHooks(准确来说是回调 URL)注册到服务商中,这个 URL 将充当接收来自 WebHooks 数据的地方。在大多数情况下,这个 URL 属于另一台服务器。WebHooks 通常用于在服务器或后端进程之间进行通信。
事件触发器:这是由你指定的运行 WebHooks 的事件。每当此事件发生时,WebHooks 都会发送请求。
WebHooks 提供程序创建 WebHooks 并发送 POST 请求: WebHooks 提供程序负责监听事件并构建 WebHooks。一旦事件被触发,WebHooks 提供程序会发送一个 HTTP POST 请求发送给第三方应用程序。
第三方应用程序接收数据:第三方应用程序将接收到数据,并转发给 URL 或者我们提供给 WebHooks 提供程序的侦听器。
第三方应用程序中指定的操作:一旦应用程序收到 POST 请求,开发人员就可以任意使用数据。
从表面上看,大概我们都会觉得这与 API 流程完全相反,因此,也有很多人将 WebHooks 称为反向 API。
重点:多方通信。
总结
对于仅需要基本 CRUD 操作和同步响应的应用程序,API 是最佳选择。而且,API 可以轻松地与 Web 和移动应用程序以及服务集成一起使用。
但是,如果我们的 Web 应用需要与后端进行实时通信,那么我们更应该选择 WebSockets,因为它允许我们在浏览器和后端之间建立双向信道。
但是,WebHooks 与 API 和 WebSockets 稍有不同,它更像是反向 API。一旦用户在服务商处注册了 WebHooks URL,后者就可以在需要时调用 WebHooks。