AJAX 与 Websocket REST over HTTP 2.0 的性能?

Posted

技术标签:

【中文标题】AJAX 与 Websocket REST over HTTP 2.0 的性能?【英文标题】:Performance of AJAX vs Websocket REST over HTTP 2.0? 【发布时间】:2016-02-21 00:05:55 【问题描述】:

Websocket 与基于 HTTP 2.0 的 AJAX 之间的实际性能差异是什么?

特别是,我正在处理的一个项目需要双向实时更新,因此,尽管不标准,但如果仅在域内发出请求,则通过 Websocket 而非 AJAX 执行 REST 可能更有效。

但是,我不确定当前可用的有关性能差异的信息是否适用于 HTTP 2.0。

【问题讨论】:

【参考方案1】:

性能应该始终经过测试而不是理论化...话虽如此,我将简要说明为什么我认为 Websocket 性能更高且更可靠

websockets 相对于轮询的优势有两个:

    在 Http/2 之前,每个新的轮询请求都需要一个新的连接。 Websockets 将为您节省与新连接相关的资源。

    显然,在使用 Http/2 时不再是这种情况,因为 Http/2 旨在利用相同的连接。继续第二个优势:

    每个新的轮询请求都是一个请求,并且需要与请求相关的所有资源(例如轮询数据库以查看更改等)。

    Websockets 将为您节省与轮询请求相关的资源,因为只有在可用时才会推送数据,从而最大限度地减少临时请求的数量。

    事实上,websockets 仍然为你节省了大量与实际轮询相关的资源。大多数 websocket 更新(如果不是全部)都使用数据更新挂钩,因此不涉及轮询(更新后立即启动推送,无需轮询和审查更改)。

    即使对 websocket 数据使用轮询,所有客户端也只有一个轮询事件,而每个客户端只有一个轮询事件。

Http/2 推送呢?

这应该可以解决性能问题...但是, 有人可能会问 - “Http/2 推送怎么样?这是否意味着不再需要 websockets?”

这有点值得商榷,您可以找到有关它的讨论(例如,here)。

从my answer到链接的问题可以看到,我相信websocket更可靠,原因如下:

此处的某些信息不在原始答案中,而我的原始答案中的其他信息被跳过或汇总

如 Http/2 草案所述(现在的标准?):

中介可以接收来自服务器的推送并选择不转发到客户端...

浏览器也是如此(如果您查看“设置”框架文档)。例如,当我在玩 Iodine's Http/2 server(我是作者)时,我注意到 Safari 将推送通知设置为“关闭”......我不确定是否仍然如此,但它是当我认为 websockets 与 Http/2 相比时,对我来说意义重大。

此外,Http/2 连接可以在浏览器仍在访问页面时由客户端(或服务器或中间的任何人)终止,从而有效地禁用 Http/2 推送通知。

当这种情况发生在 websockets 中时,onclose 回调可用于重新建立连接。使用 Http/2,您目前无能为力。

出于这些原因(以及其他一些原因),我相信 Websocket 可以提供更好的性能和更好的可靠性。

EDIT(与cmets有关)

SSE(服务器发送事件)

请允许我说明为什么我认为 websocket 优于 SSE。

SSE 是基于长轮询、前 websockets 时代的开发。

对于服务器到客户端的消息来说,它本来可以很好的,除了一些事情:

    它的服务器端实现很糟糕。

    就 Http/2 而言,我还没有看到任何实现,所以我无法评论可能会发生什么,但是:

    许多 SSE 实现将为每个连接打开一个新线程或实现与服务器的 IO 反应器一起运行的第二个 IO 反应器,仅用于管理 SSE 连接。

    与 websockets 相比,这会浪费资源(尽管我看到一些 websocket 实现做同样的事情 - brrr...)。

    SSE 是单向的,不能用于客户端到服务器发送的消息。

    这意味着您仍然使用 Http+AJAX 来处理从客户端发送到服务器的数据。

    与 Websocket 不同,SSE 和 Http+AJAX 都是无状态的,因此您需要对每个新消息周期进行身份验证,解码 Http/2 标头,编码 Http/2 标头并使用与新请求相关的所有资源...

    Websockets 允许您通过有状态来跳过所有这些。这意味着 Http 标头和身份验证仅在打开连接时执行一次,并且所有消息都在这个持续存在连接生命周期的持久上下文中发送。

    社区不太支持 SSE。

    与 Websockets 相比,很难找到与 SSE 相关的优秀库或信息...即使 SSE 早于 websockets

    我认为这很好地证明了webwebsocket在实际生产中的优越性。

Http/2 中的 Websocket 隧道

我认为这个概念和想法是错误的,不应该使用隧道。

我认为 2014 年 2 月 14 日的 the suggestion 在 2014 年 8 月 18 日到期后没有续订是有原因的(据我所知)。

以下是我能想到的几个原因:

    Websockets 和 Http/2 被设计为具有不同的生命周期和连接超时。

    虽然 Http/2 与 Http/1.1 相比寿命更长,但浏览器(或服务器)可能随时断开它们(无论是否实现 websocket 断开模式)。

    路由器、代理和负载平衡器与 Http/2 相关,以设置连接的超时设置。相同的设置不太可能适用于今天用于 websockets 的超时设置。

    Websockets 和 Http/2 是为不同的客户端设计的。

    Http/2 是为 Http 客户端设计的 - 主要是浏览器。

    另一方面,Websockets 是为所有 Web 客户端设计的,以帮助导航通过 ISP、防火墙、代理、NAT 路由器等中介。 (即this package)

    这意味着当您决定编写一个原生应用程序并将您的网络服务器用作后端时,该原生应用程序应该使用 websockets 以获得更好的连接性(它的连接性统计信息比原始的更好) TCP/IP)。

    您的本机应用程序不使用 Http/2,但它确实具有建立 websockets 连接所需的精简 Http/1。

    如果您决定使用隧道,您可能无法将当前代码用于本机应用程序。

【讨论】:

SSE(服务器发送事件)怎么样?我上次阅读时,在 HTTP/2 中,通道是通过相同的连接建立的,服务器可以将通知推送到用户代理,而无需单独的。 @vtortola 好一个! SSE 是一个非常合理的选择。 websockets 也可以在 HTTP/2 连接中建立隧道。真正的问题是如何在后端应用程序中使用这些好东西...... 你有关于隧道的文档吗?由于 websocket 和 HTTP/2 都使用二进制框架方法,我猜 HTTP/2 以某种方式包装了 WS,但是 websocket 连接请求不同的协议(ws:// 或 wss://),并且 SSE 受 SOP 影响,而WS 不是,所以我想知道在什么条件下这样的隧道是可能的。 @vtortola ,我将我对 SSE 和隧道的想法添加到我的答案中。简而言之,我会避免两者。只有当我知道我的应用程序永远不会(即使在未来的迭代中)需要从客户端请求数据时,我才会考虑 SSE……即使我不确定我会使用它。跨度> 【参考方案2】:

我肯定会使用 websockets,用那种甜美的语法少得多麻烦,但永远不要忘记使用 socket.io,因为它们是 websockets 不做 NAT 遍历,并且有更多的阻塞器,这可能会削弱你的项目。

另外一个事实是,如果你想使用 Cordova ios 和 websockets 去 WKWebView,因为你会被它们在 ios 默认浏览器中的工作方式吓到。

关于 websockets 的最后一件事是尽量不要将它们用于从客户端向服务器发送数据,仅服务器 -> 客户端,因为归根结底,AJAX 是比 websockets 更可靠的解决方案。

【讨论】:

以上是关于AJAX 与 Websocket REST over HTTP 2.0 的性能?的主要内容,如果未能解决你的问题,请参考以下文章

将 JaxRS REST 服务与 WebSocket 集成

从 REST 和服务器与客户端事件的角度理解 websocket

如何将 spring-data-rest 与 spring websocket 混合到一个实现中

websocket与ajax的区别浅析

websocket与ajax的区别浅析

Socket ,WebSocket Ajax 之间的关系与区别