222

我已经使用 WebSockets 有一段时间了,我选择使用 Node 服务器和 WebSockets 为我在大学的最后一年项目创建一个敏捷项目管理工具。我发现使用 WebSockets 使我的应用程序每秒可以处理的请求数量增加了 624%。

然而,自从开始这个项目以来,我已经阅读了安全漏洞,并且一些浏览器选择默认禁用 WebSockets..

这引出了我的问题:

当 WebSockets 似乎在降低延迟和资源开销方面做得如此出色时,为什么要使用 AJAX,有什么 AJAX 比 WebSockets 做得更好吗?

4

7 回答 7

220

WebSockets 并非旨在取代 AJAX,严格来说甚至不能替代 Comet/long-poll(尽管在很多情况下这是有意义的)。

WebSockets 的目的是在浏览器和服务器之间提供低延迟、双向、全双工和长时间运行的连接。WebSockets 为浏览器应用程序打开了新的应用程序域,这些应用程序使用 HTTP 和 AJAX(交互式游戏、动态媒体流、桥接现有网络协议等)是不可能的。

但是,WebSockets 和 AJAX/Comet 之间的目的肯定有重叠。例如,当浏览器想要收到服务器事件的通知(即推送)时,Comet 技术和 WebSockets 无疑都是可行的选择。如果您的应用程序需要低延迟推送事件,那么这将是支持 WebSockets 的一个因素。另一方面,如果您需要与现有框架和部署的技术(OAuth、RESTful API、代理、负载均衡器)共存,那么这将是支持 Comet 技术的一个因素(目前)。

如果您不需要 WebSockets 提供的特定好处,那么坚持使用 AJAX 和 Comet 等现有技术可能是一个更好的主意,因为这允许您重用和集成现有的庞大的工具、技术、安全机制生态系统, 知识库(即 stackoverflow 上知道 HTTP/Ajax/Comet 的人比 WebSockets 多得多)等。

另一方面,如果您要创建的新应用程序在 HTTP/Ajax/Comet 的延迟和连接限制下无法正常工作,那么请考虑使用 WebSockets。

此外,一些答案表明 WebSockets 的缺点之一是有限/混合的服务器和浏览器支持。让我稍微分散一下。虽然 iOS(iPhone、iPad)仍然支持旧协议 (Hixie),但大多数 WebSockets 服务器同时支持 Hixie 和 HyBi/ IETF 6455版本。大多数其他平台(如果它们还没有内置支持)可以通过web-socket-js(基于 Flash 的 polyfill)获得 WebSockets 支持。这涵盖了绝大多数网络用户。此外,如果您使用 Node 作为服务器后端,那么请考虑使用包含 web-socket-js 作为后备的Socket.IO,如果即使它不可用(或禁用),那么它将回退到使用任何 Comet 技术可用于给定的浏览器。

更新:iOS 6 现在支持当前的 HyBi/IETF 6455 标准。

于 2012-04-30T18:34:37.817 回答
80

快进到 2017 年 12 月,(实际上)每个浏览器都支持 Websocket,并且它们的使用非常普遍。

然而,这并不意味着 Websockets 成功地取代了 AJAX,至少不是完全取代,尤其是在 HTTP/2 适配正在兴起的情况下。

简短的回答是 AJAX 仍然适用于大多数 REST 应用程序,即使在使用 Websockets 时也是如此。但上帝在细节中,所以......:

AJAX 用于轮询?

使用 AJAX 进行轮询(或长轮询)正在消亡(而且应该如此),但出于两个充分的原因(主要用于较小的 Web 应用程序),它仍然在使用:

  1. 对于许多开发人员来说,AJAX 更容易编码,尤其是在编码和设计后端时。

  2. 使用 HTTP/2,与 AJAX(建立新连接)相关的最高成本被消除,从而使 AJAX 调用具有相当高的性能,尤其是在发布和上传数据时。

但是,Websocket 推送远优于 AJAX(无需重新验证或重新发送标头,无需“无数据”往返等)。这被讨论了很多次。

用于 REST 的 AJAX?

AJAX 的更好用途是 REST API 调用。这种使用简化了代码库并防止 Websocket 连接阻塞(尤其是在中等大小的数据上传时)。

有许多令人信服的理由更喜欢 AJAX 进行 REST API 调用和数据上传:

  1. AJAX API 实际上是为 REST API 调用而设计的,非常适合。

  2. 使用 AJAX 的 REST 调用和上传在客户端和后端都更容易编写代码。

  3. 随着数据负载的增加,Websocket 连接可能会被阻塞,除非对消息分段/多路复用逻辑进行编码。

    如果在单个 Websocketsend调用中执行上传,它可能会阻塞 Websocket 流,直到上传完成。这会降低性能,尤其是在速度较慢的客户端上。

一种常见的设计使用通过 Websocket 传输的小型双向消息,而 REST 和数据上传(客户端到服务器)利用 AJAX 的易用性来防止 Websocket 阻塞。

但是,在较大的项目中,Websockets 提供的灵活性以及代码复杂性和资源管理之间的平衡将使平衡倾向于 Websockets。

例如,基于 Websocket 的上传可以提供在连接断开并重新建立后恢复大型上传的能力(还记得您要上传的 5GB 电影吗?)。

通过编码上传碎片逻辑,很容易恢复中断的上传(困难的部分是编码)。

HTTP/2 推送呢?

我可能应该补充一点,HTTP/2 推送功能不会(也可能不能)取代 Websockets。

这已经在这里讨论过,但只要提到单个 HTTP/2 连接服务于整个浏览器(所有选项卡/窗口)就足够了,因此 HTTP/2 推送的数据不知道它属于哪个选项卡/窗口,消除了替代 Websocket 将数据直接推送到特定浏览器选项卡/窗口的能力。

虽然 Websockets 非常适合小型双向数据通信,但 AJAX 仍然具有许多优势 - 特别是在考虑更大的有效负载(上传等)时。

和安全?

好吧,一般来说,为程序员提供的信任和控制越多,工具就越强大......并且会出现更多的安全问题。

AJAX 本质上会占上风,因为它的安全性内置在浏览器的代码中(这有时是有问题的,但它仍然存在)。

另一方面,AJAX 调用更容易受到“中间人”攻击,而 Websockets 安全问题通常是应用程序代码中引入安全漏洞的错误(通常后端身份验证逻辑是您可以找到这些漏洞的地方)。

就我个人而言,我认为这并没有那么大的区别,如果有什么我认为 Websockets 稍微好一点的话,尤其是当你知道你在做什么的时候。

我的拙见

恕我直言,除了 REST API 调用,我会使用 Websockets。大数据上传我会尽可能分段并通过 Websockets 发送。

恕我直言,轮询应该被取缔,网络流量的成本是可怕的,而且即使对于新开发人员来说,Websocket 推送也很容易管理。

于 2017-12-22T18:40:12.797 回答
18

除了旧浏览器的问题(包括 IE9,因为从 IE10 开始将支持 WebSockets),尚不支持 WebSockets 的网络中介仍然存在很大问题,包括透明代理、反向代理和负载平衡器。有一些移动运营商完全封锁了 WebSocket 流量(即在 HTTP UPGRADE 命令之后)。

随着岁月的流逝,WebSockets 将得到越来越多的支持,但与此同时,您应该始终拥有一种基于 HTTP 的备用方法来向浏览器发送数据。

于 2012-04-30T09:20:18.840 回答
17

我读过的关于 websockets 和安全性的大部分抱怨来自 web 浏览器安全和防火墙安全工具的安全供应商。问题是他们不知道如何对 websockets 流量进行安全分析,因为一旦它完成了从 HTTP 到 websocket 二进制协议的升级,数据包内容及其含义是特定于应用程序的(基于您编写的任何内容)。对于这些以分析和分类所有互联网流量为生的公司来说,这显然是一场后勤噩梦。:)

于 2014-02-19T17:13:48.380 回答
11

WebSockets 在较旧的 Web 浏览器中不起作用,并且支持它的浏览器通常具有不同的实现。这几乎是为什么它们没有一直用来代替 AJAX 的唯一充分理由。

于 2012-04-30T01:04:22.820 回答
2

我认为我们不能对 Websockets 和 HTTP 做一个明确的比较,因为它们不是竞争对手,也不能解决相同的问题。

Websockets 是近乎实时地处理长期双向数据流的绝佳选择,而 REST 则非常适合偶尔的通信。使用 websockets 是一项相当大的投资,因此对于偶尔的连接来说它是一种过度杀伤力。

您可能会发现 Websocket 在高负载时表现更好,在某些情况下 HTTP 稍微快一些,因为它可以利用缓存。比较 REST 和 Websockets 就像比较苹果和橘子。

我们应该检查哪一个为我们的应用程序提供更好的解决方案,哪一个最适合我们的用例获胜。

于 2017-12-27T10:57:25.903 回答
1

HTTP 和 Websockets 之间差异的示例,以客户端大小的库的形式可以处理 Websocket 端点(如 REST API)和 RESTful 端点(如客户端上的 Websockets)。 https://github.com/mikedeshazer/sockrest 另外,对于那些试图在客户端使用 websocket API 或反之亦然的人来说。libs/sockrest.js 几乎清楚地说明了差异(或者说应该)。

于 2018-06-07T04:40:48.470 回答