使用Websockets代替RESTful HTTP有哪些陷阱?

97

我目前正在从事一个项目,需要客户端请求大任务并将其发送到服务器。然后服务器分割该任务,并以一系列URL的形式响应客户端进行GET调用并流回数据。我是这个项目中的新手,目前正在使用Spring WebSockets来提高效率。与客户端不断ping服务器以查看是否有结果要返回的方法不同,现在WebSocket将直接与客户端联系,太好了!

完全由WebSocket管理整个过程是否是一个坏主意?我正在使用带有Spring WebSockets的STOMP,放弃REST还会有重大问题吗?

3个回答

164

通过RESTful HTTP,您拥有一个无状态的请求/响应系统,其中客户端发送请求,服务器返回响应。

通过webSockets,您拥有一个有状态(或潜在的有状态)的消息传递系统,可以双向发送消息,并且发送消息的开销比RESTful HTTP请求/响应要低。

这两者具有相当不同的结构和不同的优势。

连接的WebSocket的主要优点是:

  1. 双向通信。 因此,服务器可以随时通知客户端任何事情。因此,客户端可以建立一个webSocket,只需侦听来自服务器的任何消息即可,而不必定期轮询服务器以查看是否有新内容。从服务器的角度来看,当客户端感兴趣的事件发生时,服务器只需向客户端发送一条消息。使用普通HTTP,服务器无法做到这一点。

  2. 每个消息的开销较低。 如果您预计客户端和服务器之间会流量大量流动,则webSocket每个消息的开销较低。这是因为TCP连接已经建立,您只需要在已打开的套接字上发送消息。使用HTTP REST请求,您必须首先建立一个TCP连接,这是客户端和服务器之间的几次来回。然后,您发送HTTP请求,接收响应并关闭TCP连接。即使这些与特定请求无关,HTTP请求也必须包括所有与该服务器对齐的所有cookie的一些开销。 HTTP/2(最新的HTTP规范)允许在客户端和服务器都使用它时在这方面获得一些额外的效率,因为可以对单个TCP连接进行多个请求/响应。如果您绘制了在TCP级别上进行的所有请求/响应,以进行https REST请求/响应,您会惊讶地发现要比仅通过已建立的webSocket发送消息要复杂得多。

  • 在某些情况下,具有更高的规模。由于每个消息的开销较低且没有客户端轮询以查找新内容,这可能会导致增加可伸缩性(给定服务器可以为更多客户端提供服务)。WebSocket 可伸缩性也存在一些缺点(请参见下文)。

  • 有状态的连接。无需使用 cookie 和会话 ID,您可以直接为特定连接在程序中存储状态。尽管已经进行了大量开发以解决大多数问题的无状态连接,但有时仅仅使用有状态连接会更简单。

  • RESTful HTTP 请求/响应的主要优势:

    1. 通用支持。很难比 HTTP 更受到普遍支持。虽然现在 WebSocket 的支持相对良好,但仍存在一些情况下 WebSocket 的支持并不常见。

    2. 与更多服务器环境兼容。有些服务器环境不允许长时间运行的服务器进程(一些共享托管情况)。这些环境可以支持 HTTP 请求,但无法支持长时间运行的 WebSocket 连接。

    3. 在某些情况下,具有更高的规模。WebSocket 要求连续连接的 TCP 套接字在服务器基础设施方面增加了一些新的规模要求,而 HTTP 请求不需要。因此,这最终成为一个权衡空间。如果 WebSocket 的优点实际上并不是真正需要或者在显着方式下被使用,则 HTTP 请求可能实际上会更好地满足可伸缩性要求。这肯定取决于特定用法配置文件。

    4. 对于一次请求/响应,单个 HTTP 请求比建立 WebSocket、使用它然后关闭它更有效率。这是因为打开 WebSocket 从 HTTP 请求/响应开始,然后在双方同意升级到 WebSocket 连接之后,才能发送实际的 WebSocket 消息。

    5. 无状态。 如果您的工作不会因为拥有无状态基础设施而变得更加复杂,那么无状态的世界可以使扩展或故障转移更加容易(只需在负载均衡器后添加或删除服务器进程)。

    6. 自动缓存。 通过正确的服务器设置,HTTP响应可以被浏览器或代理缓存。对于通过webSockets发送的请求,没有这样的内置机制。

    7. 因此,针对您提出的问题:

      在RESTful HTTP的位置使用WebSocket的缺陷是什么?

      1. 在大规模(数十万个客户端)下,您可能需要进行一些特殊的服务器工作,以支持大量同时连接的webSockets。

      2. 并非所有可能的客户端或工具集都支持webSockets或通过它们发送的请求与支持HTTP请求的同样程度。

      3. 一些价格较低的服务器环境不支持长时间运行的服务器进程,这是支持webSockets所必需的。

      如果向客户端返回进度通知对您的应用程序很重要,则可以使用长时间运行的http连接,并继续发送进度,或者您可以使用webSocket。 webSocket可能更容易。 如果您真的只需要webSocket来处理此特定活动的相对较短的持续时间,那么您可能会发现在需要能够将数据推送到客户端时仅使用webSocket,并使用http请求进行正常的请求/响应活动是最好的总体权衡集。


    1
    感谢您的详细回答。我仍在等待那个神奇的框架,使得WebSockets成为构建网络应用程序的事实标准。我真的很喜欢Spring在WebSockets方面所做的工作。也许它将在未来演变成为一些重大的东西。 - smuggledPancakes
    为什么没有人提到REST响应是可缓存的,而且没有简单/自动缓存Websocket结果的方法? - metamaker
    2
    @metamaker - 这是一个合理的观点,我会加上它。但是WebSocket连接通常不用于请求/响应类型的活动,缓存也不相关,事实上,HTTP通常是纯请求/响应的推荐选择。 - jfriend00
    1
    @jfriend00 没错,但这绝对是 REST 相对于 WebSockets 闪耀的使用案例。 - metamaker
    1
    在支持方面,我们的浏览器几乎达到了100%:https://caniuse.com/#feat=websockets - Rexcirus
    显示剩余3条评论

    5
    “这真的取决于您的需求。与Websockets相比,REST服务可以更加透明和易于开发者使用。”
    “使用Websockets,您会失去大部分RESTful Web服务提供的优势,例如通过URI引用资源的能力。实际上,您应该弄清REST和超媒体的优势,然后根据这些决定这些优势对您是否重要。”
    “当然,完全可能创建一个RESTful Web服务,并且增加一个基于Websocket的API以获得实时响应。”
    “但是,如果您正在创建一个只有您自己在受控环境中使用的服务,唯一的缺点可能是并非所有客户端都支持Websockets,而几乎任何类型的环境都可以进行简单的HTTP调用。”

    通过Spring-websockets和Spring-messaging,我能够进行/@MessageMapping以获得URI。我也能够进行Spring-mvc /@RequestMapping调用!看起来Spring-websockets可以允许RESTful的抽象?这就是我迷失的地方,可能是因为我太天真了,但它使得websocket开发变得非常有吸引力,但我没有听到太多关于它的嗡嗡声。 - smuggledPancakes

    0

    在阅读其他答案后,我总结了以下内容或指南:

    1. 如果您想快速向服务器发送数据,即具有较小的延迟,例如实时消息传递,则使用WebSocket

    2. 如果用户再次请求资源几秒钟后可能包含更改,但您希望他无需手动刷新即可意识到这一点,则使用WebSocket

    3. 在任何其他情况下,请使用HTTP


    你的回答可以通过添加更多支持信息来改进。请[编辑]以添加详细信息,例如引文或文献资料,以便他人可以确认你的答案是否正确。你可以在帮助中心找到有关如何编写好的答案的更多信息。 - Community

    网页内容由stack overflow 提供, 点击上面的
    可以查看英文原文,
    原文链接