SSE 与 WebSocket

2024-04-17

在本文中,我们将比较服务器发送事件(sse)和 websocket,两者都是用于传递数据的可靠方法。我们将在八个方面对它们进行分析,包括通信方向、底层协议、安全、易用性、性能、消息结构、易用性和测试工具。这些方面的比较总结如下:类别服务器发送事件 (sse)websocket通信方向单向双向底层协议httpwebsocket 协议安全与 http 相同存在安全漏洞易用性设置简单设置复杂性能消息发送速度快受消息处理和连接管理影响消息结构纯文本文本或二进制易用性广泛可用对 websocket 集成有需求测试工具使用 postman 和集合使用 jmeter、gadling、sse-perf、testable 或 k6

在今天的文章中,我想仔细研究一下服务器发送事件(简称 SSE)和 WebSocket。两者都是经过实践检验的良好数据交换方法。

SSE 与 WebSockets 图像

我将从这两种工具的简短特征开始——它们是什么以及它们提供什么。然后,我将根据八个类别对它们进行比较,在我看来,这对于现代系统来说是最重要的。

类别如下:

  • 沟通方向

  • 底层协议

  • 安全

  • 简单

  • 表现

  • 消息结构

  • 易于采用

  • 工装

与我之前比较REST 和 gRPC 的比较相比,我不会宣布每个类别有任何获胜者或授予分数。相反,在摘要段落中,您会发现一种 TL;DR 表。该表包含两种技术在上述领域的主要区别。

为什么

与 REST 不同,SSE 和 WebSocket 都更注重用例。在这个特定的情况下(或多个情况),这两个概念的主要焦点是提供“实时”通信媒介。由于其特定的重点,它们不如 REST 受欢迎,REST 是一种更通用且一刀切的工具。

尽管如此,SSE 和 WebSocket 都提供了一系列有趣的可能性,并且与解决问题的经典 REST 方法相比略有更新。

在我看来,了解它们并在我们的工具箱中为它们找到一些空间是件好事,因为有一天它们可能会派上用场,为您提供一个更简单的解决方案来解决相当复杂的问题 - 特别是当您需要“真正的” -时间”更新或当您的应用程序需要更加面向推送的方法时。

除了在这里对它们进行比较和描述之外,我还想让它们更受欢迎。

什么是 WebSocket?

简而言之,WebSockets 是一种通信协议,它使用单个持久的TCP 连接在服务器和客户端之间提供双向通信。由于这个功能,我们不必不断地从服务器提取新数据。相反,数据是在感兴趣的各方之间“实时”交换的。每条消息都是二进制数据或 Unicode 文本。

IETF于 2011 年以RFC 6455的形式对该协议进行了标准化。 WebSocket 协议与 HTTP 不同,但两者都位于OSI 模型的第 7 层,并依赖于第 4 层的 TCP。

该协议有其独特的前缀集,其工作方式与 HTTP 前缀“http”和“https”类似:

  • ws - 表示连接未使用 TLS 进行保护

  • wss - 指示连接受 TLS 保护

此外,不应该从安全站点 (https) 打开非安全 WebSocket 连接 (ws)。同样,不应从非安全站点 (http) 打开安全 WebSocket 连接 (wss)。

另一方面,WebSocket 在设计上工作在 HTTP 端口 443 和 80 上,并支持代理和中介等 HTTP 概念。此外,WebSocket 握手使用 HTTP 升级标头将协议从 HTTP 升级到 WebSocket。

WebSocket 作为协议的最大缺点是安全性。 WebSocket不受同源策略的限制,这可能会让类似CSRF的攻击变得更加容易。

什么是服务器发送的事件?

SSE 是一种允许 Web 服务器向网页发送更新的技术。它是 HTML 5 规范的一部分,与 WebSocket 类似,利用单个长期 HTTP 连接“实时”发送数据。

在概念层面上,它是相当古老的技术,其理论背景可以追溯到 2004 年。Opera 团队于 2006 年实施了第一个实施 SSE 的方法。

大多数现代浏览器都支持 SSE - Microsoft Edge 于 2020 年 1 月添加了 SSE 支持。它还可以充分利用 HTTP/2,这消除了 SSE 的最大问题之一,实际上消除了由HTTP/1.1。

根据定义,服务器发送事件有两个基本构建块:

  • EventSource - 基于WHATWG 规范并由浏览器实现的接口,它允许客户端(在本例中为浏览器)订阅事件。

  • 事件流- 一种协议,描述服务器发送的事件的标准纯文本格式,EventSource 客户端必须遵循该格式才能理解和传播它们。

根据规范,事件可以携带任意文本数据、可选 ID,并由换行符分隔。他们甚至有自己独特的 MIME 类型:text/event-stream.

不幸的是,服务器发送事件作为一种技术被设计为仅支持基于文本的消息,尽管我们可以使用自定义格式发送事件,但最终消息必须是 UTF-8 编码的字符串。

更重要的是,SSE 提供了两个非常有趣的功能:

  • 自动重新连接- 如果客户端意外断开连接,EventSource 会定期尝试重新连接。

  • 自动流恢复 - EventSource 自动记住上次收到的消息 ID,并在尝试重新连接时自动发送 Last-Event-ID 标头。

比较

沟通方向

两者之间最大的区别可能是他们的沟通方式。

  • SSE 仅提供单向通信——事件只能从服务器发送到客户端。

  • WebSockets 提供完整的双向通信,使感兴趣的各方能够交换信息并对双方的任何事件做出反应。

我想说,这两种方法都有其优点和缺点,并且每种方法都有一组专用的用例。

一方面,如果您只需要向客户端推送持续更新的流,那么 SSE 将是更合适的选择。另一方面,如果您需要以任何方式对其中一个事件做出反应,那么 WebSocket 可能更有利。

从理论上(和实践)来看,所有可以用 SSE 完成的事情也可以用 WebSocket 完成,但是我们正在进入支持、解决方案的简单性或安全性等领域。

我将在下面的段落中描述所有这些领域以及更多内容。此外,在所有情况下使用 WebSocket 都可能是一种严重的矫枉过正,而基于 SSE 的解决方案可能更容易实现。

底层协议

这是两种技术之间的另一个巨大差异。

  • SSE 完全依赖于 HTTP,并且支持 HTTP/1.1 和 HTTP/2。

  • 相比之下,WebSocket 使用自己的自定义协议——令人惊讶的是——WebSocket 协议。

就 SSE 而言,利用 HTTP/2 解决了 SSE 的主要问题之一——最大并行连接限制。 HTTP/1.1 根据其规范限制了并行连接的数量。

此行为可能会导致称为队头阻塞的问题。 HTTP/2 通过引入多路复用解决了这个问题,从而解决了应用层的 HOL 阻塞。然而,队头阻塞仍然可能发生在 TCP 级别。

关于WebSocket协议,我在上面几行已经详细提到过。在这里,我只是重申最重要的几点。尽管使用 HTTP 升级标头来初始化 WebSocket 连接并有效地更改通信协议,但该协议与经典 HTTP 略有不同。

尽管如此,它也使用 TCP 协议作为基础,并且与 HTTP 完全兼容。 WebSocket协议最大的缺点是它的安全性。

简单

一般来说,设置基于 SSE 的集成比其 WebSocket 集成更简单。其背后最重要的原因是特定技术所利用的通信的本质。

SSE 的单向方式及其推送模型使其在概念层面上变得更容易。将其与开箱即用的自动重新连接和流连续性支持相结合,我们需要处理的事情显着减少。

凭借所有这些功能,SSE 也可以被视为减少客户端和服务器之间耦合的一种方法。客户端只需要知道产生事件的端点即可。

然而,在这种情况下,客户端只能接收消息,因此如果我们想要将任何类型的信息发送回服务器,我们需要另一种通信介质,这可能会使事情变得非常复杂。

就 WebSocket 而言,情况有些复杂。首先,我们需要处理从HTTP协议到WebSockets协议的连接升级。尽管这是最简单的事情,但这是我们需要记住的另一件事。

第二个问题来自 WebSocket 的双向特性。我们必须管理特定连接的状态并处理处理消息时发生的所有可能的异常。例如,如果处理其中一条消息在服务器端引发异常怎么办?

接下来是处理重新连接的问题,对于 WebSockets,我们必须自己处理。

还有一个影响这两种技术的问题——长时间运行的连接。

这两种技术都需要维持长期的开放连接以发送连续的事件流。

管理此类连接(尤其是大规模连接)可能是一项挑战,因为我们很快就会耗尽资源。此外,它们可能需要特殊配置,例如延长超时,并且更容易遇到任何网络连接问题。

安全

就 SSE 而言,安全性没有什么特别之处,因为它使用普通的旧 HTTP 协议作为传输介质。所有标准 HTTP 的优点和缺点都适用于 SSE,就这么简单。

另一方面,安全性是整个 WebSocket 协议的最大缺点之一。首先,不存在“同源策略”这样的东西,因此对于我们想要通过 WebSocket 连接的位置没有限制。

甚至还有一种旨在利用此漏洞的特定类型的攻击,即跨源 WebSocket 劫持。如果您想更深入地了解同源策略和 WebSocket 主题,这里有一篇您可能感兴趣的文章。除此之外,WebSocket 中不存在特定于协议的安全漏洞。

我想说,在这两种情况下,所有标准和最佳安全实践都适用,因此在实施解决方案时要小心。

表现

我想说这两种技术在性能方面是平等的。这两种技术本身都不存在理论上的性能限制。

然而,我想说,就每秒发送的消息数量而言,SSE 可以更快,因为它遵循即发即忘的原则。 WebSocket 还需要处理来自客户端的响应。

唯一可以影响它们两者性能的是我们在应用程序中使用的底层客户端及其实现。检查、阅读文档、运行自定义压力测试,您最终可能会对您正在使用的工具或整个系统有非常有趣的了解。

消息结构

消息结构可能是协议之间最重要的差异之一。

正如我上面提到的,SSE 是一个纯文本协议。我们可以发送不同格式和内容的消息,但最终一切都以 UTF-8 编码的文本结束。不可能有复杂的格式或二进制数据。

另一方面,WebSocket 可以处理文本和二进制消息。让我们能够发送图像、音频或只是常规文件。请记住,处理文件可能会产生很大的开销。

易于采用

在这里,这两种技术处于非常相似的阶段。从 SSE 的角度来看,有很多工具可以添加 WebSocket 和服务器发送事件支持(客户端和服务器)。

大多数已建立的编程语言都有多个这样的库。无需赘述太多细节。我准备了表格,总结了基本库,添加了 WebSockets 和 SSE 支持。

爪哇:

    Spring SSE / WebSockets

    Quarkus SSE / WebSockets

斯卡拉:

    像SSE / WebSockets

    播放/ WebSockets

JavaScript

    事件源

    Total.js SSE/WebSocekts

    Socket.io

Python

    小明星

    快速API

正如您所看到的,如果我们想将 SSE 或 WebSockets 集成添加到我们的应用程序中,我们有很多成熟的选择。当然,这只是从所有库中挑选的一个很小的例子;还有更多。真正的问题可能是找到最适合您的特定用例的一种。

工装

自动化测试

据我所知,SSE 或 WebSockets 都没有自动化测试工具。但是,使用Postman和集合可以相对轻松地实现类似的功能。

Postman 支持服务器发送事件和WebSockets。通过使用源自 Postman 集合的一些魔法,您可以准备一组测试来验证端点的正确性。

性能测试

对于性能测试,您可以使用 JMeter 或 Gadling。据我所知,这是两个最成熟的整体性能测试工具。当然,它们都还支持SSE(JMeter,Gadling)和WebSockets(JMeter,Gadling)。

还有其他工具,例如sse-perf(仅限 SSE)、Testable或k6(仅限 WebSockets)。

在所有这些工具中,我个人推荐 Gattle 或 k6。两者似乎都具有最佳的用户体验并且最适合生产。

文档

在某种程度上,没有专门用于记录 SSE 或 WebSocket 的工具。另一方面,有一个名为AsyncAPI的工具,它可以以这种方式用于这两个概念。

不幸的是,OpenAPI似乎不支持SSE 或 WebSockets。

概括

正如我所承诺的,总结将是快速而简单的——请看下面。

WebSockets 和 SSE 之间的比较表

我认为上表是对主题和整篇文章的一个很好而紧凑的总结。

最重要的区别是通信方向,因为它决定了特定技术的可能用例。它可能会对选择其中之一产生最大的影响。

在选择特定的通信方式时,消息结构也可能是一个非常重要的类别。仅允许纯文本消息是服务器发送事件的一个非常重要的缺点。

以上就是SSE 与 WebSocket的详细内容,更多请关注北冥有鱼其它相关文章!