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

时间:2012-09-23 18:27:13

标签: javascript web-applications websocket comet http-streaming

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

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

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

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

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

WebSockets:他们是新的API,试图通过以下方式解决上述方法的缺点:

  • WebSockets相对于Java Applet,Flash或Silverlight等插件的唯一优势是WebSockets本身内置于浏览器中,不依赖于插件。
  • WebSockets优于http流的唯一优势是您无需“理解”并解析收到的数据。
  • WebSockets优于长轮询的唯一优势是消除了额外的标头大小&打开和关闭请求的套接字连接。

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

谢谢!

4 个答案:

答案 0 :(得分:82)

与您确定的差异有很多不同。

双面/定向:

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

为了增加延迟(近似值):

  • 的WebSockets
  • 插件网络
  • HTTP流媒体
  • HTTP long-poll
  • HTTP轮询

CORS(跨域支持):

  • WebSockets:是的
  • 插件网络:通过政策请求发送Flash(不确定其他人)
  • HTTP *(最近的一些支持)

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

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

带宽效率下降:

  • 插件网络:除初始策略请求外,Flash套接字是原始的
  • WebSockets:连接设置握手和每帧几个字节
  • HTTP流媒体(重新使用服务器连接)
  • HTTP long-poll:每条消息的连接
  • HTTP轮询:每条消息的连接+无数据消息

移动设备支持:

  • WebSocket:iOS 4.2及更高版本。一些Android通过Flash模拟或使用Firefox for AndroidGoogle Chrome for Android两者都提供原生WebSocket支持。
  • 插件网络:一些Android。不在iOS上
  • HTTP *:大部分都是

Javascript使用复杂度(从最简单到最复杂)。无可否认,复杂性措施有点主观。

  • 的WebSockets
  • HTTP民意调查
  • 插件网络
  • HTTP长轮询,流式传输

另请注意,有一个名为Server-Sent Events的标准化HTTP流的W3C提案。它目前还处于早期发展阶段,旨在提供与WebSockets相似的标准Javascript API。

答案 1 :(得分: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已经有这种能力至少10年了,但它并不普遍。

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

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

虽然针对这些情况的某种回退策略是明智的,甚至是必要的,但大多数使用Flash等的人都会遇到上述缺点。它并非必须如此 - 有使用Flash,Silverlight等实现安全的跨源连接的解决方法 - 但大多数实现都不会这样做,因为它并不容易

例如,如果您依赖WebSocket进行跨源连接,那么它将正常工作。但是,如果您在旧的浏览器或受干扰的防火墙/代理中运行并依赖Flash,比如说,作为您的后备,您将发现难以进行相同的跨源连接。当然,除非你不关心安全问题。

这意味着难以拥有一个适用于本机和非本机连接的统一架构,除非您准备投入大量工作或使用已经完成它的框架好。在理想的架构中,您不会注意到连接是否是本机连接;您的安全设置在两种情况下都有效;您的群集设置仍然有效;你的容量规划仍然存在;等等。

  

WebSockets优于http流的唯一优势是您不必努力理解"并解析收到的数据。

它并不像打开HTTP流那样简单,只需数据流动几分钟,几小时或更长时间就可以了。不同的客户端行为不同,您必须管理它。例如,某些客户端将缓冲数据,并且在满足某个阈值之前不会将其释放到应用程序。更糟糕的是,在连接关闭之前,有些人不会将数据传递给应用程序。

因此,如果您向客户端发送多封邮件,则客户端应用程序可能无法接收数据,直到收到50条有关数据的邮件为止。那不是太实时。

虽然当WebSocket不可用时,HTTP流式传输可能是一种可行的选择,但它并不是万能药。在现实世界的条件下,需要很好地理解在网络的荒地中以健壮的方式工作。

  

我还缺少其他重大差异吗?

还有一件事没有提到,所以我会提出来。

WebSocket协议旨在成为更高级别协议的传输层。虽然您可以直接通过WebSocket连接发送JSON消息或什么不是,但它也可以携带标准或自定义协议。

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

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

(当然,您希望能够安全地完成所有操作,因此请与供应商或WebSocket提供商联系。)

有些人将WebSocket称为Web的TCP。因为就像TCP传输更高级别的协议一样,WebSocket也是如此,但其方式与Web基础设施兼容。

因此,尽管通过WebSocket直接发送JSON(或其他)消息总是可行的,但也应考虑现有协议。因为对于你想要做的很多事情,可能已经考虑过这样做的协议。

  

对不起,如果我重新询问或将SO上已有的许多问题合并到一个问题中,但我只想完全理解SO上的所有信息。关于这些概念的网站。

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

答案 2 :(得分:10)

  

如果我可能会问另外一件事:我在某篇文章中看到过,http流式传输也可能由代理缓存,而websockets则不会。这是什么意思?

(StackOverflow限制了评论回复的大小,所以我不得不在这里回答而不是内联。)

这是一个好点。要理解这一点,请考虑一下传统的HTTP场景......想象一下,浏览器打开了一个网页,所以请求http://example.com。服务器使用包含页面HTML的HTTP进行响应。然后浏览器看到页面中有资源,因此它开始请求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和业务逻辑时,往往不得不关心他们不应该关注的事情 - 他们不应该关注底层的沟通。

答案 3 :(得分:4)

HTTP将客户端与服务器的连接数限制为2(尽管可以通过使用子域来缓解这种情况),并且已知IE已经急切地强制执行此操作。 Firefox和Chrome允许更多(虽然我不记得我的头脑究竟有多少)。这似乎不是一个大问题,但如果您经常使用1个连接进行实时更新,则所有其他请求都必须通过其他HTTP连接进行瓶颈。而且客户端拥有更多开放连接的问题会给服务器带来更多负担。

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