使用Websockets代替RESTful HTTP有什么陷阱?


76

我目前正在从事一个项目,该项目要求客户端请求一项繁重的工作并将其发送到服务器。然后,服务器对作业进行划分,并为客户端提供一个URL数组,以进行GET调用并流回数据。我是该项目的新手,目前正在使用Spring Websocket来提高效率。Websocket现在将直接联系客户端hooray,而不是客户端不断ping服务器以查看是否有准备好流回的结果。

让websockets从头到尾管理整个过程是否是一个坏主意?我正在将STOMP与Spring websockets一起使用,放弃REST还会有重大问题吗?

Answers:


124

使用RESTful HTTP,您可以拥有一个无状态的请求/响应系统,在该系统中,客户端发送请求,服务器返回响应。

使用webSocket,您可以有状态(或可能有状态)的消息传递系统,其中消息可以以任何一种方式发送,并且发送消息的开销比RESTful HTTP请求/响应低。

两者是具有不同强度的完全不同的结构。

连接的webSocket的主要优点是:

  1. 双向通讯。 因此,服务器可以随时将任何情况通知客户端。因此,客户端可以建立一个webSocket并仅侦听来自服务器的任何消息,而不是定期轮询服务器以查看是否有新消息。从服务器的角度来看,当发生客户端感兴趣的事件时,服务器只是向客户端发送一条消息。服务器无法使用纯HTTP执行此操作。

  2. 降低每条消息的开销。 如果您预计客户端和服务器之间将有大量流量,那么使用webSocket的每条消息的开销会更低。这是因为TCP连接已经建立,您只需要在已经打开的套接字上发送消息即可。对于HTTP REST请求,您必须首先建立一个TCP连接,该连接在客户端和服务器之间来回连接。然后,您发送HTTP请求,接收响应并关闭TCP连接。HTTP请求将必然包含一些开销,例如与该服务器对齐的所有cookie,即使这些cookie与特定请求无关。如果客户端和服务器都使用HTTP / 2(最新的HTTP规范),则在这方面可以提高一些效率,因为单个TCP连接可以用于多个请求/响应。

  3. 在某些情况下规模更高。 由于每条消息的开销较低,并且没有客户端轮询来查找是否有新消息,因此可以增加可伸缩性(给定服务器可以服务的客户端数量更多)。webSocket可伸缩性也有缺点(请参见下文)。

  4. 有状态的连接。 无需使用Cookie和会话ID,您可以直接将状态存储在程序中以获取给定的连接。尽管无状态连接已经完成了许多开发工作,可以解决大多数问题,但有时使用有状态连接则更加简单。

RESTful HTTP请求/响应的主要优点是:

  1. 普遍支持。 很难获得比HTTP更通用的支持。尽管webSockets现在获得了相对良好的支持,但在某些情况下,webSocket支持并不经常可用。

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

  3. 在某些情况下规模更高。 连续连接TCP套接字的webSocket要求为HTTP请求不需要的服务器基础结构增加了一些新的扩展要求。因此,这最终成为一个权衡的空间。如果不需要真正使用webSockets的优点,或者不需要大量使用webSockets的优点,那么HTTP请求实际上可以更好地扩展。绝对取决于特定的使用情况。

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

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

  6. 自动可缓存。 使用正确的服务器设置,http响应可以由浏览器或代理缓存。通过webSockets发送的请求没有这种内置机制。


因此,按照您提出问题的方式进行处理:

使用Websocket代替RESTful HTTP有什么陷阱?

  1. 在大规模(数十万个客户端)中,您可能必须执行一些特殊的服务器工作才能支持大量同时连接的webSocket。

  2. 所有可能的客户端或工具集都不支持webSocket或通过其发出的请求达到与支持HTTP请求相同的级别。

  3. 一些较便宜的服务器环境不支持支持webSocket所需的长时间运行的服务器进程。

如果将进度通知返回给客户端对于您的应用程序很重要,则可以使用长时间运行的http连接并向下发送连续的进度,也可以使用webSocket。webSocket可能更容易。如果您确实只需要在相对较短的时间内执行特定的活动,那么您可能会发现最好的整体折衷方案是仅在需要将数据推送到客户端的时间段内使用webSocket然后将http请求用于正常的请求/响应活动。


1
感谢您的详细回答。我仍在等待使websockets成为构建Web应用程序的实际方法的神奇框架。我真的很喜欢Spring对Websockets所做的事情。也许它会演变为未来的重大事物。
走私

为什么没人提到REST响应是可缓存的,并且没有简单/自动的方法来缓存Websocket的结果?
metamaker'6

1
@metamaker-这是一个合理的观点,我将添加它。但是,对于与缓存相关的活动,webSocket连接通常不用于请求/响应类型的活动,实际上,对于纯请求/响应,http通常是推荐的选择。
jfriend00

@ jfriend00确实如此,但是与WebSockets相比,这是REST闪耀的明确用例。
metamaker'6

在支持方面,对于浏览器,我们几乎达到100%:caniuse.com/#feat=websockets
Rexcirus

3

这确实取决于您的要求。与Websockets相比,REST服务可以更加透明,并且更易于开发人员使用。

使用Websocket,可以消除RESTful Web服务提供的大多数优点,例如通过URI引用资源的能力。实际上,您应该做的是弄清楚REST和超媒体的优点,然后根据这些优点确定这些优点是否对您很重要。

当然,完全有可能创建一个RESTful Web服务,并使用基于websocket的API进行实时响应以对其进行扩充。

但是,如果创建的服务只能在受控环境中使用,则唯一的缺点可能是并非每个客户端都支持websocket,而几乎任何类型的环境都可以执行简单的http调用。


使用Spring-websockets和Spring-messaging,我可以执行/ @ MessageMapping以拥有URI。我也可以做一个Spring-mvc / @ RequestMapping调用!看起来Spring-websockets可以允许像RESTful这样的抽象吗?这是我迷路的地方,可能是因为我天真,但是这使websocket开发看起来确实很有吸引力,但是我对此并没有听到太多嗡嗡声。
走私
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.