原文链接:https://ably.com/topic/socketio-vs-http

在规划实时应用程序时,您应该仔细考虑要使用哪些技术。本文对Socket.IO实时库和HTTP协议进行了比较。下面您将了解每种解决方案的功能、每种解决方案的优缺点以及何时使用它们。

什么是Socket.IO?

Socket.IO 是一个创建于 2010 年的库,提供客户端和服务器之间的实时双向通信。它允许管理连接、发送和接收消息等等。这使得 Socket.IO 成为构建消息/聊天应用程序的理想选择。

Socket.IO 需要两个库 - 一个在服务器上,一个在客户端上。 Socket.IO 创建者维护以下“官方”:

一些 Socket.IO 客户端和服务器实现可以用其他语言实现。请阅读Socket.IO 是什么来获取列表。

下图总结了典型的 Socket.IO 设置:

img

Socket.IO 主要特性

Socket.IO 具有以下主要特性:

  • **向后兼容性:**在现代浏览器中,Socket.IO 使用WebSocket API提供所需的连接并发送消息。 WebSocket 在服务器和浏览器之间提供全双工、低延迟、事件驱动的连接。它也是有状态的。如果需要旧版浏览器支持,或者 WebSocket 连接无法使用(由于防火墙或公司代理),Socket.IO 可以回退到 HTTP 和长轮询。
  • 重连和缓冲: Socket.IO提供自动重连功能。当客户端断开连接时,数据包会自动缓冲,并在重新连接时发送。
  • 多种数据格式: Socket.IO 支持任何可序列化格式的数据传输,包括BufferTypedArray等二进制对象。
  • **致谢:**使用 Socket.IO,一旦成功接收到消息就可以发送响应消息。
  • 命名空间: Socket.IO 使您能够设置具有不同客户端、房间、事件和应用程序逻辑的不同通道。
  • **广播到不同的客户端组:**从服务器,您可以向所有连接的客户端或子集发送消息。

Socket.IO 的优缺点

Socket.IO 专业人士

  • 连接效率: Socket.IO 使用 HTTP 长轮询发起连接,一旦建立可用性就升级到 WebSocket(有关更多详细信息,请参阅升级机制)。当发生这种情况时,客户端-服务器连接使用单个 WebSocket,而不必启动多个连接,从而减少延迟并改善用户体验。
  • **客户端和服务器发起的通信:**由于WebSocket提供了全双工、双向的通信通道,因此服务器可以向客户端发送消息,并且两者可以同时发送消息。
  • 事件驱动的通信: WebSocket是一种事件驱动的协议,这意味着您可以在收到消息后立即监听并响应消息,而不是使用轮询机制来检查更新,这样既浪费又低效。
  • 丰富的功能集: Socket.IO 提供了实现实时应用程序所需的一切。当使用原始 HTTP 甚至原始 WebSocket 时,您必须自己实现其中大部分功能。
  • 有状态: Socket.IO 使用 WebSocket,它是有状态的。该状态一直持续到连接关闭为止。

Socket.IO 缺点

  • **有限的平台支持:**我们之前提到,Socket.IO 在不同的平台和语言上有多种服务器和客户端实现。值得一提的是,其中一些没有得到积极维护,或者功能集有限,因此在考虑使用它们之前请仔细检查它们。此外,Socket.IO 实现与本机 WebSocket 不兼容,因为 Socket.IO 会向其发送的每个数据包添加额外的元数据。
  • 可扩展性: Socket.IO 非常适合有限数量用户的实时通信应用程序。但是,如果您的用户数量和数据量开始变大,您的服务器可能会过载。当您的服务器达到最大负载时,您将需要将连接拆分到多个服务器上,否则可能会丢失重要信息。这种增加的架构复杂性带来了更多问题。阅读Scaling Socket.IO - 实际注意事项以获取更多信息。
  • **内存泄漏:**已知 Socket.IO 存在一些与内存泄漏相关的问题。内存泄漏不太可能导致任何直接问题,但如果您的应用程序使用了很长一段时间,它们最终可能会导致用户的设备冻结或崩溃。

什么是 HTTP?

HTTP 是一种请求/响应协议,作为 Web 的主要通信机制,构建在 TCP 网络协议之上。有限版本最初由 Tim Berners-Lee 于 1989 年提出,随后经过快速修改以支持更广泛的浏览器和服务器功能。 HTTP 工作组于 1996 年将这些修改记录为 HTTP/1.0 ( RFC 1945 )。

HTTP 在 RESTful 架构(即 REST API)中很常见。 REST 的经典用例是 CRUD 应用程序,其中 HTTP POST、PUT、GET、PUT 和 DELETE 动词提供了一种简单的方法来实现创建、读取、更新和删除数据的操作。

传统的 HTTP 消息流如下所示:

img

HTTP 技术的出现可以实现实时应用程序:

  • 长轮询**:**对 HTTP 服务器的重复请求会浪费资源 - 在每个请求中,您都必须建立一个新连接,解析 HTTP 标头,查询新数据,生成和传递响应,以及关闭和清理连接。长轮询通过尽可能长时间地保持客户端-服务器连接打开,在新数据可用或达到超时阈值时提供响应来改进这一点。正如本文前面提到的,当 WebSocket 不可用时,Socket.IO 会转而使用 HTTP 长轮询。
  • 服务器发送事件 (SSE) SSE 允许浏览器订阅服务器生成的事件流,并在新事件发生时接收更新。 EventSource接口接受特定 URL 处的 HTTP 流连接,并在检索可用数据时保持连接打开。 SSE 听起来像是 WebSocket 的有力竞争对手,但它是单向的。

HTTP 关键特性

我们已经看到了 HTTP 的多个新版本,每个版本都添加了新功能。

  • **HTTP/1.1 (1997):**引入了一些重要的增强功能,最显着的是Keep-Alive标头(允许连接处理多个请求)和Upgrade标头(将连接升级到增强协议,例如 WebSockets)。
  • **HTTP/2 (2015):**这是一项性能更新,旨在提高 Web 通信的速度。 HTTP/2 包括:
    • 多路复用,涉及帧内的二进制数据封装,沿着多个称为流的双向通道发送,全部通过单个 TCP 连接,允许同时发生许多并行请求/响应。
    • 服务器推送,一种允许服务器在客户端请求响应之前将响应发送到兼容 HTTP/2 的客户端的功能。当服务器知道客户端需要“推送”响应来完全处理原始请求时,此功能非常有用。
  • **HTTP/3(自 2018 年开始开发):**旨在使用称为 QUIC 的不同传输层网络协议解决 HTTP/2 的传输相关问题(例如延迟),该协议在用户数据报协议 (UDP) 而不是 TCP 上运行。

HTTP 的优点和缺点

HTTP 优点:

  • **平台支持:**每个服务器端平台和非浏览器客户端平台(想想用 Kotlin 构建的 Android 客户端,或用 Rust 构建的桌面应用程序)都具有出色的 HTTP 支持。如果您使用的平台对 Socket.IO 等库没有良好的支持,您可能会选择在标准 HTTP 之上实现解决方案。

HTTP 缺点:

  • **连接效率:**尽管 Keep-Alive 标头和长轮询允许在每个连接上发送多个请求,但仍然需要多个连接,并且开销比基于 WebSocket 的解决方案(如 Socket.IO)更大。这会导致延迟增加和用户体验变差。
  • **单向通信:**在标准 HTTP 中,所有请求均由客户端发起,响应由服务器处理。 SSE 提供来自服务器的通信流,但这仍然只是单向的。
  • **缺乏事件驱动的通信:**尽管 SSE 允许在事件发生时使用事件来响应来自服务器的消息。在服务器上监听和响应来自客户端的消息仍然需要轮询机制来不断检查更新,这是浪费且低效的。
  • **有限的功能集:**使用原始 HTTP 将要求您自己实现应用程序所需的功能集,或者找到其他库来帮助您。
  • **无状态:**每次通信完成后,连接关闭,状态丢失。

Socket.IO 和 HTTP 有什么区别?

下表快速总结了 Socket.IO 和 HTTP 之间的主要区别。

套接字IOHTTP协议
良好的浏览器兼容性,可回退到 HTTP 长轮询优秀的浏览器兼容性
服务器端平台兼容性和非浏览器客户端兼容性尚可,部分地方存在差距出色的服务器端和非浏览器客户端兼容性
双向通讯单向通讯
事件驱动的通信非事件驱动通信(使用 SSE,事件驱动通信仅适用于从服务器到客户端)
出色的连接效率——一旦建立,WebSocket 连接的整个生命周期都需要单个 TCP 连接连接效率良好——通信生命周期内需要多个连接
有状态的无国籍
丰富的功能集功能需要自行实现

我应该使用 Socket.IO 还是 HTTP?

这取决于您的用例;在本节中,我们将研究两者的合适用例。

何时使用 Socket.IO

Socket.IO 非常适合构建涉及多个用户和服务器之间的消息交换的任何应用程序,您希望在其中维护整体状态并希望获得响应式双向实时用户体验。示例包括聊天/消息应用程序、多用户游戏、协作编辑(例如 Google 文档)、基于位置的应用程序等。

Socket.IO 具有良好的跨浏览器兼容性,但其对不同平台(即非 JavaScript/Node.js)的支持可能参差不齐。如果您使用的是良好支持的客户端/服务器组合,并且您不关心支持旧版浏览器,那么 Socket.IO 就可以了。如果您需要替代方案,请阅读我们的Socket.IO 替代方案文章以获取选项。

何时使用 HTTP

HTTP 非常适合多用户应用程序,在这些应用程序中,您不需要两个方向的实时响应,但您仍然关心每个客户端和服务器之间可靠、安全的数据交换。想想传统的 REST/CRUD 应用程序——银行应用程序、电子邮件应用程序、天气应用程序和电子商务应用程序。

如果您想要实时响应,但仅限于从服务器到客户端,那么 SSE 是一个可行的解决方案。 SSE 对于提供实时信息更新的应用程序很有用,但用户只是消费数据,而不是写入数据。很好的例子可能包括股票行情或新闻行情应用程序。

HTTP 是一项非常成熟的技术,对 Web 浏览器、服务器平台和非浏览器客户端类型提供大力支持。如果您担心对 Socket.IO 等库的支持不完整,请考虑使用原始 HTTP 构建您的应用程序。

总体而言,Socket.IO 和 HTTP 哪个更好?

您应该使用 Socket.IO 还是 HTTP 取决于您的用例。 Socket.IO 等基于 WebSocket 的解决方案对于构建具有低延迟、高效连接和高性能要求的实时应用程序至关重要。然而,当涉及到平台兼容性和可扩展性时,Socket.IO 可能会下降——如果这些出现问题,HTTP 可能是更好的方法。

Ably 是 Socket.IO 的替代品,具有强大的发布/订阅消息传递、针对每种主要语言和开发平台的超过 25 个 SDK、可用的专门专家支持等等。有关详细比较,请参阅Ably 与 Socket.IO。借助可用的 WebSocket 和 REST 库,您可以轻松集成。