聊天应用程序可以使用 HTTP REST API 吗?

Is it ok to use HTTP REST API for Chat application?

我们正在 Android 上构建聊天应用程序。我们正在考虑使用 HTTP REST API 发送出站消息。想知道与使用 WebSockets 或 XMPP(这似乎更像是传输聊天消息的事实标准)相比,这是一种好方法还是有任何缺点?

我能想到的一些 pros/cons 是:

根据这份文件,似乎 Facebook 最初也使用 AJAX 来处理聊天消息:

https://www.erlang-factory.com/upload/presentations/31/EugeneLetuchy-ErlangatFacebook.pdf

我认为 REST 方法可以用于聊天。让我们假设:

如果我没理解错的话,你的问题是关于最后一点的。

客户端向 http://chat.example.com/conversations/123 发送出站消息后,它将关闭 http 连接。

缺点是在这种情况下根本不可能接收入站消息。您将需要一个不同的频道(可能只是 Google cloud messaging)。

相反,WebSockets 和 XMPP 使连接保持活动状态,因此它们可以毫无延迟地接收消息。但两者的缺点确实是,就可扩展性而言,这代表了服务器的成本;以及客户在电池使用方面的成本。

在服务器上:

  • 套接字是一种相对稀缺的资源
  • 如果客户端有一个开放的连接,就不可能为了负载均衡而移动它们(但是你真的可以移动客户端吗?这取决于层级的职责)

在客户端:

  • 维护网络连接非常昂贵。 1 秒网络 ≈ 5 分钟睡眠。
  • XMPP librairies are not necessarily working very well on Android。 我不知道 support of WebSockets on android.

我们可以使用 REST API 进行聊天消息传递,但恕我直言,XMPP 是更好的选择。让我们考虑一下 XMPP 必须提供的功能。

XMPP 除了支持 TCP 传输还提供 HTTP(通过 pollingbinding)和 websocket 运输。阅读 XMPP via HTTP and WebSocket transports

从 XMPP 的角度了解每种传输的优缺点会很有趣。

XMPP could use HTTP in two ways: polling[18] and binding.

基于 HTTP 轮询的 XMPP

The polling method, now deprecated, essentially implies messages stored on a server-side database are being fetched (and posted) regularly by an XMPP client by way of HTTP 'GET' and 'POST' requests.


基于 HTTP 绑定的 XMPP (BOSH)

绑定方法被认为比轮询方法中的常规 HTTP 'GET' 和 'POST' 请求更有效,因为它比其他方法减少了延迟和带宽消耗HTTP 轮询技术

但是,这也带来了一个缺点,即套接字会长时间保持打开状态,等待客户端的下一个请求

The binding method, implemented using Bidirectional-streams Over Synchronous HTTP (BOSH),[19] allows servers to push messages to clients as soon as they are sent. This push model of notification is more efficient than polling, where many of the polls return no new data.

如果我们了解 the BOSH technique 的工作原理就好了。

The technique employed by BOSH, which is sometimes called "HTTP long polling", reduces latency and bandwidth consumption over other HTTP polling techniques. When the client sends a request, the connection manager does not immediately send a response; instead it holds the request open until it has data to actually send to the client (or an agreed-to length of inactivity has elapsed). The client then immediately sends a new request to the connection manager, continuing the long polling loop.

If the connection manager does not have any data to send to the client after some agreed-to length of time [12], it sends a response with an empty . This serves a similar purpose to whitespace keep-alives or XMPP Ping (XEP-0199) [13]; it helps keep a socket connection active which prevents some intermediaries (firewalls, proxies, etc) from silently dropping it, and helps to detect breaks in a reasonable amount of time.


基于 WebSocket 绑定的 XMPP

XMPP 支持 WebSocket 绑定,这是一种更高效的传输方式

A perhaps more efficient transport for real-time messaging is WebSocket, a web technology providing for bi-directional, full-duplex communications channels over a single TCP connection. XMPP over WebSocket binding is defined in the IETF proposed standard RFC 7395.

说到学习曲线,是的,您可能很想使用 REST API,但是现在有一些资源可以学习 Android and XMPP, and XMPP server softwares,您可以使用这些资源 运行 您自己的 XMPP 服务,可以通过 Internet 或局域网。在您决定您的体系结构之前花费这些努力是值得的。

不建议将 HTTP Rest API 用于聊天或类似的实时应用程序。

一些概述...

聊天客户端要求

  1. 获取好友列表

  2. 查看online/offline个朋友

  3. 实时获取聊天消息并发送消息。

  4. 接收delivery/reading等通知

第 1 点是启动聊天客户端后的一次性工作,因此可以通过简单的休息调用来完成,因此不需要复杂的开销。

在 p2p 客户端的情况下,其余所有点都需要持续检查来自服务器或其他部分的数据。这将使您创建长轮询或短轮询休息调用以监视新数据或其他更新。

HTTP Rest 客户端有问题

它不是一种保持活动的通信类型,因此您将不得不建立多个 HTTP 连接,这会产生大量开销,以至于变得过于缓慢。由于重新连接在 HTTP 调用中成本很高。

Web 套接字或 XMPP 它们是双工通信模式,非常擅长处理增量数据推送,并且您不会再次创建新的 HTTP 连接,因此它提供了非常流畅的性能。

另一种解决方案 如果您受困于某些遗留系统,在这种情况下您必须使用其余 API 模式。

尝试 CometD 它是 WebSockets 和 ajax 轮询的混合方法,可以为您提供接近实时的通信以及在不支持的客户端上工作WebSockets 通过回退 ajax 轮询机制。此外,它使用各种优化来避免一次又一次地重新连接。

CometD link

你也可以试试Socket.io这也是解决这类用例的神奇技术

简答号

我不会开始一个新项目或建议开始一个新项目(因为你提到重新开始)需要依赖 HTTP 的实时双向通信 - 作为无状态协议。您可能会对连接保持活动状态感到欣慰,但不能保证。

您的 + HTTP endpoint is easy to scale horizontally on server side 专业人士在 HTTP 用作请求和响应样式以及它被视为无状态时的上下文中是专业人士。当您本质上需要保持连接活动时,它就变得有些没有实际意义(尽管不完全是)。

HTTP 确实提供了您未在此处提及的另一个好处。

  • HTTP is easy to deal with corporate firewall proxies when other ports may be blocked.

这就是其他人提到的 WebSockets 或 XMPP over HTTP 的成功率更高的地方。

视情况而定。你认为你的申请是"live chat"吗?您需要存在指示器或打字指示器吗?诸如此类的功能需要持续连接。但是还有另一组聊天应用程序,您将其描述为 "in-app messaging" 已启用。这些应用程序在某种后端存储对话和对话列表;只需在另一台设备上安装该应用程序并登录,您就会在此类应用程序上看到您的对话。这些应用程序没有任何存在指示器或活跃感。

虽然我还没有使用 XMPP 实现任何应用程序,但就消息持久性而言,您会发现 XMPP(开箱即用)的最大持久性是持续到发送,类似于 SMS .也许您可以通过在节通过时捕获节并将它们存储在您自己的数据库中来为 XMPP 构建 storage/recovery 机制。但是,如果您不需要完整的 "chat" 体验,使用数据库、HTTP 服务和推送通知(通知更新的线程)似乎是具有消息传递功能的应用程序的可靠途径——我打算在iOS & Android 我自己的应用程序。

如果您为此找到任何好的开源 schemas/API 设计,请告诉我。