我对HTTP轮询,长轮询,HTTP流和WebSocket的理解


123

我在SO和网络上阅读了很多有关我的问题标题中的关键字的帖子,并从中学到了很多。我读的一些问题与特定的实施挑战有关,而其他问题则与一般概念有关。我只是想确保我了解所有概念以及为什么发明技术X而不是发明技术Y的理由等等。因此,这里去:

Http轮询:基本上是AJAX,使用XmlHttpRequest。

Http Long Polling: AJAX,但服务器保留响应,除非服务器进行了更新,一旦服务器进行了更新,它将发送该更新,然后客户端可以发送另一个请求。缺点是需要来回发送的附加头数据,导致额外的开销。

Http流传输:类似于长轮询,但是服务器使用带有“传输编码:分块”的标头进行响应,因此我们不需要每次服务器发送一些数据时就发起一个新请求(从而节省了额外的标头开销)。这里的缺点是我们必须“理解”并弄清楚数据的结构,以区分服务器发送的多个块。

Java Applet,Flash,Silverlight:它们提供了通过tcp / ip连接到套接字服务器的功能,但是由于它们是插件,因此开发人员不想依赖它们。

WebSockets:它们是新的API,它试图通过以下方式解决上述方法的不足:

  • WebSockets相对于Java Applet,Flash或Silverlight等插件的唯一优势是WebSockets内置于浏览器中,并且不依赖于插件。
  • 与HTTP流相比,WebSockets的唯一优势是您不必费力“理解”和解析收到的数据。
  • WebSockets相对于Long Polling的唯一优势在于,它消除了额外的标头大小以及为请求打开和关闭套接字连接。

我还有其他重大差异吗?很抱歉,如果我要重新提出或将关于SO的许多问题合并为一个问题,但是我只想从SO和Web上有关这些概念的所有信息中完全理解。

谢谢!


4
当您不需要双向通信时,服务器发送的事件可能也值得一看。
leggetter 2012年

1
这是一个非常有用的问题。我认为,如果有一个答案可以被多位作者做出贡献,那么它可能会更有用。
leggetter 2012年

@leggetter感谢Phil,感谢您提供有关服务器发送事件的提示。我对学习双向通信方案感兴趣。谢谢。
软件专家2012年

1
使用HTTP流和长轮询,您需要第二个连接来进行双向通信。服务器的一个较长的连接->客户端“推送”通信,而客户端的另一个短寿命的连接->服务器通讯。第二个连接用于执行诸如设置和更改数据订阅的操作。因此,EventSource可以用于双向解决方案,实际上实际上是源自HTTP流和长轮询的标准化解决方案。
leggetter 2012年

1
您可能还需要检查出的技术这种分类我写道:stackoverflow.com/questions/12078550/...
亚历山德罗Alinone

Answers:


92

存在的差异比您已发现的差异更多。

双工/定向:

  • 单向:HTTP轮询,长轮询,流式传输。
  • 双向:WebSockets,插件网络

按增加的延迟顺序(大约):

  • Web套接字
  • 插件网络
  • HTTP流
  • HTTP长轮询
  • HTTP轮询

CORS(跨域支持):

  • WebSockets:是的
  • 插件联网:通过策略请求进行刷新(不确定其他人)
  • HTTP *(最近的一些支持)

本机二进制数据(类型化数组,blob):

  • WebSockets:是的
  • 插件网络:不支持Flash(需要在ExternalInterface上进行URL编码)
  • HTTP *:最近建议启用二进制类型支持

带宽降低效率:

  • 插件网络:Flash套接字是原始请求请求请求之外的原始套接字
  • WebSockets:连接设置握手,每帧几个字节
  • HTTP流传输(重新使用服务器连接)
  • HTTP长轮询:每个消息的连接
  • HTTP轮询:每条消息的连接+没有数据消息

移动设备支持:

JavaScript使用复杂性(从最简单到最复杂)。诚然,复杂性度量在一定程度上是主观的。

  • Web套接字
  • HTTP轮询
  • 插件网络
  • HTTP长轮询,流式传输

另请注意,有一个W3C建议用于标准化HTTP流,称为Server-Sent Events。它目前尚处于发展初期,旨在提供一种标准的Javascript API,且具有与WebSockets相当的简单性。


1
非常感谢Kanaka的好评。您能告诉我为什么/流媒体延迟比websockets高吗?也许举一个简单的例子?非常感谢。
软件专家2012年

2
@SoftwareGuy。很多原因。在最近的浏览器上,可以使用XMLHTTPRequest onprogress事件处理程序来通知数据。但是规范说50ms是最小的通知间隔。否则,您必须轮询以获取响应数据。此外,客户端发送会建立新的HTTP连接,因此会大大增加往返延迟。同样,许多Web服务器在30秒左右后就会断开HTTP连接,这意味着您通常必须继续重新建立服务器推入连接。我已经在本地网络上看到5-10毫秒的WebSocket往返延迟。HTTP流延迟可能超过50毫秒。
kanaka 2012年

非常感谢您的详细答复:)
软件专家

1
@leggetter谢谢Phil,您的意思是通过HTTP流从客户端向服务器发送数据会导致开销吗?是否可以通过HTTP流向服务器发送数据而无需打开新连接?谢谢。
Software Guy 2012年

1
@Nathan听起来像是一个优秀的硕士学位论文项目!当然,轮询将使系统比事件驱动的模型更忙,但要节省多少电量,则需要在不同规模上进行相当广泛的经验测试。
kanaka

13

其他人的一些很好的答案涵盖了很多方面。还有一些额外的东西。

WebSockets相对于Java Applet,Flash或Silverlight等插件的唯一优势是WebSockets内置于浏览器中,并且不依赖于插件。

如果这表示您可以使用Java Applet,Flash或Silverlight建立套接字连接,那么可以。但是,由于这些限制,您不会看到在现实世界中部署得太频繁。

例如,中介可以并且确实会关闭该流量。WebSocket标准旨在与现有的HTTP基础结构兼容,因此不太容易受到诸如防火墙和代理之类的中介的干扰。

而且,WebSocket可以使用端口80和443,而无需专用端口,这再次要归功于协议设计与现有HTTP基础结构尽可能兼容。

这些套接字替代方案(Java,Flash和Silverlight)很难在跨域体系结构中安全使用。因此,经常尝试跨源使用它们的人会容忍这种不安全感,而不是去努力地安全地做到这一点。

他们还可能需要打开其他“非标准”端口(管理员不愿意这样做)或需要管理的策略文件。

简而言之,使用Java,Flash或Silverlight进行套接字连接很成问题,以至于您不会看到它经常部署在严重的体系结构中。Flash和Java至少有十年拥有此功能,但是并不普遍。

WebSocket标准能够从一种全新的方法开始,牢记这些限制,并希望从中吸取一些教训。

当无法建立WebSocket连接时(例如,在旧的浏览器中运行或中介干扰时),某些WebSocket实现使用Flash(或可能的Silverlight和/或Java)作为后备。

尽管针对这些情况的某种后备策略是明智的,甚至是必要的,但大多数使用Flash等人的策略都会遭受上述缺点的困扰。不一定要这样-有一些变通办法可以使用Flash,Silverlight等实现安全的跨域连接,但是大多数实现不会这样做,因为这并不容易。

例如,如果您依赖WebSocket进行跨域连接,则可以正常工作。但是,如果您随后在旧的浏览器中运行,或者防火墙/代理受到干扰并依赖Flash,例如,作为后备,您将发现很难进行相同的跨域连接。当然,除非您不在乎安全性。

这意味着很难有一个适用于本机和非本机连接的统一体系结构,除非您准备进行大量工作或使用做得很好的框架。在理想的体系结构中,您不会注意到连接是否是本地的。您的安全设置在两种情况下都可以使用;您的群集设置仍然可以使用;您的容量规划将仍然有效;等等。

与HTTP流相比,WebSockets的唯一优势是您不必费力“理解”和解析收到的数据。

这不像打开HTTP流然后坐下来等待您的数据流持续几分钟,几小时或更长时间那样简单。不同的客户的行为不同,您必须对此进行管理。例如,某些客户端将缓冲数据,直到达到某个阈值才将其释放给应用程序。更糟糕的是,直到关闭连接,有些人才会将数据传递给应用程序。

因此,例如,如果您要向客户端发送多条消息,则客户端应用程序可能直到接收到50条消息的数据才接收数据。那不是实时的。

当WebSocket不可用时,HTTP流传输可以作为可行的替代方法,但这并不是万能的。在现实情况下,要以健壮的方式在Web的荒地中工作,它需要很好的理解。

我还有其他重大差异吗?

还没有人提到过另一件事,所以我将其提起。

WebSocket协议被设计为更高层协议的传输层。虽然您可以直接通过WebSocket连接发送JSON消息或诸如此类的消息,但它也可以承载标准或自定义协议。

例如,您可以通过WebSocket进行AMQP或XMPP,就像人们已经做过的那样。因此,客户端可以从AMQP代理接收消息,就像它直接连接到代理本身一样(在某些情况下是这样)。

或者,如果您现有的服务器具有某些自定义协议,则可以通过WebSocket传输该服务器,从而将该后端服务器扩展到Web。通常,已锁定在企业中的现有应用程序可以使用WebSocket扩展其范围,而无需更改任何后端基础结构。

(自然,您希望能够安全地执行所有操作,因此请与供应商或WebSocket提供程序联系。)

有些人将WebSocket称为Web的TCP。因为就像TCP传输高级协议一样,WebSocket也是如此,但是以与Web基础结构兼容的方式进行。

因此,尽管始终可以直接通过WebSocket发送JSON(或其他任何消息)消息,但也应考虑现有协议。因为对于您想做的许多事情来说,可能已经有人考虑过要这样做。

很抱歉,如果我重新提出或将关于SO的许多问题合并为一个问题,但是我只想从SO和Web上有关这些概念的所有信息中完全理解。

这是一个很好的问题,答案都非常有用!


非常感谢Robin提供的出色帮助和信息。如果我可能要再问一件事:我在一篇文章中碰到过一个文章,该文章说HTTP流也可能被代理缓存,而Websocket却没有。那是什么意思?
Software Guy 2012年

由于StackOverflow的响应意见限制大小,我已经给我的回答如下: stackoverflow.com/questions/12555043/...
罗宾·齐默尔曼

@RobinZimmermann,您的回答是我的最爱。+1是非常好的详细答案。
securecurve 2012年

10

如果我可能要再问一件事:我在一篇文章中碰到过一个文章,该文章说HTTP流也可能被代理缓存,而Websocket却没有。那是什么意思?

(StackOverflow限制了评论响应的大小,因此我不得不在这里回答而不是内联。)

那是个很好的观点。要理解这一点,请考虑一下传统的HTTP场景...想象一下,浏览器打开了一个网页,因此它请求http://example.com。服务器以HTTP响应,该HTTP包含页面的HTML。然后浏览器发现页面中有资源,因此它开始请求CSS文件,JavaScript文件和图像。它们都是静态文件,对于所有请求它们的客户端来说都是相同的。

一些代理将缓存静态资源,以便来自其他客户端的后续请求可以从代理获取这些静态资源,而不必一直回到中央Web服务器来获取它们。这是缓存,这是从中央服务卸载请求和处理的好策略。

因此,客户#1请求http://example.com/images/logo.gif。该请求一直通过代理服务器到达中央Web服务器,该中央服务器提供了logo.gif。当logo.gif通过代理服务器时,代理服务器将保存该图像并将其与地址http://example.com/images/logo.gif关联。

当客户端#2出现并且还请求http://example.com/images/logo.gif时,代理可以返回图像,并且不需要通信返回中心的Web服务器。这给最终用户带来了更快的响应,这总是很棒的,但是这也意味着中心上的负载更少。这可以转化为降低硬件成本,降低网络成本等。因此这是一件好事。

在Web服务器上更新logo.gif时,会出现问题。代理将继续提供旧映像,而不会意识到存在新映像。这导致整个过期,因此代理将仅在图像“过期”之前对其进行高速缓存,并且下一个请求通过代理到达Web服务器,然后刷新服务器的缓存。还有一些更高级的解决方案,其中中央服务器可以将其推送到已知的缓存中,依此类推,事情可能会变得非常复杂。

这与您的问题有何关系?

您询问有关HTTP流传输的信息,其中服务器正在将HTTP流传输到客户端。但是,流HTTP与常规HTTP一样,只是您不会停止发送数据。如果Web服务器提供图像,则它将HTTP发送到最终结束的客户端:您已经发送了整个图像。而且,如果您要发送数据,则完全相同,但是服务器仅发送了很长时间(例如,这是一个巨大的图像),甚至永无休止。

从代理的角度来看,它无法区分静态资源(如图像)的HTTP还是HTTP流中的数据。在这两种情况下,客户端都向服务器发出请求。代理记住了该请求以及响应。下次该请求进入时,代理服务器提供相同的响应。

因此,如果您的客户提出了例如股票价格的请求并得到了响应,那么下一个客户可能会发出相同的请求并获取缓存的数据。可能不是您想要的!如果您要求股票价格,您需要最新数据,对吗?

所以这是一个问题。

有一些技巧和变通办法可以解决类似的问题,这是事实。显然,由于HTTP流已在使用中,因此您可以使其正常工作。所有这些对于最终用户都是透明的,但是开发和维护这些体系结构的人必须跳过障碍并付出一定的代价。这会导致架构过于复杂,这意味着需要更多的维护,更多的硬件,更多的复杂性和更多的成本。这也意味着,当开发人员只专注于应用程序,GUI和业务逻辑时,它们通常不必关心某些事情,而不必关心底层的通信。


1
出色的细节Robin,非常感谢!我非常感谢您的详尽回应。我已经从这里所有的伟大人士那里学到了很多东西!:)
软件专家

4

HTTP将客户端与服务器之间的连接数限制为2(尽管可以通过使用子域来减轻连接数),并且已知IE会积极地强制执行此操作。Firefox和Chrome可以提供更多功能(尽管我不记得到底有多少个)。这看起来似乎不是一个大问题,但是如果您不断使用1个连接进行实时更新,则所有其他请求都必须通过另一个HTTP连接成为瓶颈。还有一个问题,那就是来自客户端的更多开放连接会给服务器增加负担。

WebSockets是基于TCP的协议,因此不会受到HTTP级别的连接限制(但是,当然,浏览器支持并不统一)。


感谢thejuice,因此,除了您强调的多个同时连接问题之外,关于websocket的其他假设是否正确?
Software Guy
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.