提问者:小点点

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


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

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

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

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

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

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

  • 与Java小程序,Flash或Silverlight等插件相比,WebSockets的唯一优势在于,WebSockets是本地内置到浏览器中的,并且不依赖于插件。
  • 与http流相比,WebSockets的唯一优点是您不必努力“理解”和解析接收到的数据。
  • 与长轮询相比,WebSockets的唯一优点是消除了额外的报头大小&打开和关闭用于请求的套接字连接。

还有其他我遗漏的显著差异吗?我很抱歉,如果我重新提出或将SO上的许多问题组合成一个单一的问题,但我只想从SO上和网络上关于这些概念的所有信息中获得完美的意义。

谢啦!


共3个答案

匿名用户

有更多的差异比你已经确定的。

双工/定向:

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

按延迟增加的顺序(近似):

  • WebSockets
  • 插件网络
  • HTTP流
  • HTTP长轮询
  • HTTP轮询

CORS(跨源支持):

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

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

  • WebSockets:是
  • 插件网络:不使用闪存(需要跨外部接口的URL编码)
  • HTTP*:启用二进制类型支持的最新建议

降低效率时的带宽:

  • 插件网络:除了初始策略请求之外,闪存套接字都是原始的
  • WebSockets:连接设置握手和每帧几个字节
  • HTTP流(服务器连接的重用)
  • HTTP Long-Poll:每个消息的连接
  • HTTP轮询:每个消息的连接+无数据消息

移动设备支持:

  • WebSocket:iOS 4.2及更高版本。一些Android通过Flash仿真或使用Firefox for Android或Google Chrome for Android,它们都提供本地WebSocket支持。
  • 插件网络:一些Android。不在IOS上
  • HTTP*:大部分是

Javascript使用复杂性(从最简单到最复杂)。诚然,复杂性度量有些主观。

  • WebSockets
  • HTTP轮询
  • 插件网络
  • HTTP长轮询,流

还要注意,W3C提出了一个标准化HTTP流的建议,称为服务器发送的事件。它目前处于发展的早期阶段,旨在提供标准Javascript API,其简单性与WebSockets相当。

匿名用户

来自其他人的一些很好的回答,涵盖了很多领域。这是额外的一点。

WebSockets相对于像Java小程序,Flash或Silverlight这样的插件的唯一优势是,WebSockets本身就内置在浏览器中,并且不依赖于插件。

如果您的意思是可以使用Java小程序,Flash或Silverlight来建立套接字连接,那么是的,那是可能的。然而,由于这些限制,在现实世界中并不经常部署这种配置。

例如,中介可以并且确实关闭了该流量。WebSocket标准被设计为与现有的HTTP基础设施兼容,因此很少受到防火墙和代理等中介的干扰。

此外,WebSocket可以使用端口80和443而不需要专用端口,这也是由于协议设计尽可能与现有HTTP基础设施兼容。

那些套接字替代方案(Java,Flash和Silverlight)很难在跨源架构中安全地使用。因此,人们往往试图使用他们的交叉起源将容忍不安全,而不是去努力做它的安全。

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

简而言之,使用Java,Flash或Silverlight来实现套接字连接是一个很大的问题,以至于您不会经常看到它部署在严肃的体系结构中。Flash和Java拥有这种功能已经至少10年了,但它并不普遍。

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

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

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

例如,如果您依赖WebSocket进行跨源连接,那么就可以很好地工作。但是如果你运行在一个旧的浏览器或防火墙/代理受到干扰,并且依赖Flash,比如说,作为你的后援,你会发现很难做同样的跨源连接。当然,除非你不在乎安全。

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

WebSockets相对于http流的唯一优势是,您不必费力“理解”和解析接收到的数据。

这并不像打开一个HTTP流,然后在您的数据流过几分钟,几小时或更长时间后坐视不管那么简单。不同的客户行为不同,你必须管理好这一点。例如,一些客户机将对数据进行缓冲,直到达到某个阈值时才将其释放到应用程序。更糟糕的是,有些直到连接关闭才会将数据传递给应用程序。

因此,如果您向客户机发送多条消息,那么客户机应用程序可能在收到50条数据消息之后才会收到数据。那不太实时。

当WebSocket不可用时,HTTP流可以是一个可行的替代方案,但它不是灵丹妙药。它需要一个很好的理解,以一个健壮的方式工作,在恶劣的网络环境下,在现实世界的条件。

还有其他我遗漏的显著差异吗?

还有一件事没人提过,所以我要提出来。

WebSocket协议被设计为更高层协议的传输层。虽然您可以发送JSON消息或其他--不是直接通过WebSocket连接,但它也可以携带标准或自定义协议。

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

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

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

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

因此,虽然直接通过WebSocket发送JSON(或其他消息)消息总是可能的,但也应该考虑现有的协议。因为对于许多你想要做的事情,可能已经有了一个协议来完成它。

我很抱歉,如果我重新提出或将SO上的许多问题组合成一个单一的问题,但我只想从SO上和网络上关于这些概念的所有信息中获得完美的意义。

这是一个很好的问题,所有的答案都很有帮助!

匿名用户

如果我可以再问一件事:我在某处看到一篇文章说http流也可以被代理缓存,而websockets不是。那是什么意思?

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

说得好。要理解这一点,请考虑一个传统的HTTP场景。。。假设一个浏览器打开了一个网页,因此它请求http://example.com。服务器使用包含页面HTML的HTTP进行响应。然后浏览器看到页面中有资源,因此它开始请求CSS文件,JavaScript文件,当然还有图像。它们都是静态文件,对于所有请求它们的客户端都是相同的。

一些代理将缓存静态资源,以便其他客户机的后续请求可以从代理获取这些静态资源,而不是必须一路返回到中央web服务器才能获取这些资源。这就是缓存,它是从中央服务中卸载请求和处理的一个很好的策略。

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

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

当在web服务器上更新logo.gif时,问题就会出现。代理将继续为旧映像服务,而不知道存在新映像。这导致整个事情都在过期,因此代理只会在映像“过期”之前缓存映像一小段时间,下一个请求通过代理到web服务器,然后web服务器刷新代理的缓存。还有一些更高级的解决方案,中央服务器可以将其推出到已知的缓存,等等,事情可能会变得非常复杂。

这和你的问题有什么关系?

您询问了HTTP流,服务器正在将HTTP流传输到客户端。但是流式HTTP就像常规HTTP一样,只是你不会停止发送数据。如果web服务器提供一个映像,它将HTTP发送到客户端,客户端最终结束:您已经发送了整个映像。如果你想发送数据,也是一样的,但是服务器只会发送很长时间(就像是一个巨大的图像),甚至永远不会完成。

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

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

所以这是个问题。

确实有一些技巧和变通方法来处理那样的问题。显然,您可以让HTTP流工作,因为它是它的使用今天。它对最终用户来说是透明的,但是开发和维护这些体系结构的人必须克服重重困难并付出代价。它导致了过于复杂的架构,这意味着更多的维护,更多的硬件,更多的复杂性,更多的成本。这还意味着开发人员经常需要关心一些他们不应该关心的事情,而他们应该只关注应用程序,GUI和业务逻辑--他们不应该关心底层通信。