我在SO和网上看了很多关于我的问题 Headers 中的关键词的帖子,并从中学到了很多 . 我读到的一些问题与具体的实施挑战有关,而其他问题则侧重于一般概念 . 我只是想确保我理解为什么技术X是在技术Y上发明的所有概念和原因等等 . 所以这里是:
Http Polling: 基本上是AJAX,使用XmlHttpRequest .
Http Long Polling: AJAX但服务器保留响应,除非服务器有更新,一旦服务器有更新,它发送它然后客户端可以发送另一个请求 . 缺点是需要来回发送额外的头数据会导致额外的开销 .
Http Streaming: 与长轮询类似,但服务器使用带有"Transfer Encoding: chunked"的标头进行响应,因此每次服务器发送一些数据时都不需要发起新请求(因此节省了额外的标头开销) . 这里的缺点是我们必须"understand"并找出数据的结构,以区分服务器发送的多个块 .
Java Applet, Flash, Silverlight: 它们提供了通过tcp / ip连接到套接字服务器的能力,但由于它们是插件,开发人员不希望依赖它们 .
WebSockets: 它们是新API,它试图通过以下方式解决上述方法的缺点:
-
WebSockets相对于Java Applet,Flash或Silverlight等插件的唯一优势是WebSockets本身内置于浏览器中,不依赖于插件 .
-
WebSockets优于http流的唯一优势是您无需努力"understand"并解析收到的数据 .
-
WebSockets优于长轮询的唯一优势是消除额外的头大小以及打开和关闭请求的套接字连接 .
我还缺少其他重大差异吗?如果我重新询问或将SO上已有的许多问题合并到一个问题中,我很抱歉,但我只是想从SO和网络上有关这些概念的所有信息中完全理解 .
谢谢!
4 回答
与您发现的差异相比,存在更多差异 .
双面打印/方向:
单向:HTTP轮询,长轮询,流式传输 .
Bi-direcitonal:WebSockets,插件网络
按顺序增加延迟(近似值):
WebSockets
插件网络
HTTP流媒体
HTTP长轮询
HTTP轮询
CORS(跨域支持):
WebSockets:是的
插件网络:通过政策请求获取Flash(不确定其他人)
HTTP *(最近的一些支持)
本机二进制数据(类型化数组,blob):
WebSockets:是的
插件网络:不使用Flash(需要跨ExternalInterface进行URL编码)
HTTP *:最近提议启用二进制类型支持
带宽效率下降:
插件网络:除初始策略请求外,Flash套接字是原始的
WebSockets:连接 Build 握手和每帧几个字节
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流,称为Server-Sent Events . 它目前还处于早期发展阶段,旨在提供标准的Javascript API,其简单性与WebSockets相当 .
来自其他人的一些很好的答案涵盖了很多方面 . 这里有点多余 .
如果这意味着您可以使用Java Applet,Flash或Silverlight来 Build 套接字连接,那么是的,这是可能的 . 但是,由于这些限制,您不会经常在现实世界中部署这些内容 .
例如,中介可以并且确实关闭该流量 . WebSocket标准旨在与现有的HTTP基础架构兼容,因此不太容易受到防火墙和代理等中介的干扰 .
此外,WebSocket可以使用端口80和443而无需专用端口,这要归功于协议设计与现有HTTP基础架构尽可能兼容 .
那些套接字替代品(Java,Flash和Silverlight)很难在跨源架构中安全使用 . 因此,经常试图使用它们来源的人会容忍不安全感,而不是努力安全地做到这一点 .
他们还可能需要打开额外的“非标准”端口(管理员不愿意这样做)或需要管理的策略文件 .
简而言之,使用Java,Flash或Silverlight进行套接字连接是有问题的,以至于您不会经常在严肃的架构中看到它 . Flash和Java已经拥有这项功能至少10年,但它并不普遍 .
WebSocket标准能够以一种全新的方法开始,并考虑到这些限制,并希望从中吸取教训 .
当无法 Build WebSocket连接时(例如在旧浏览器中运行或中间干扰时),某些WebSocket实现使用Flash(或可能是Silverlight和/或Java)作为其后备 .
虽然针对这些情况的某种回退策略是明智的,甚至是必要的,但大多数使用Flash等的人都会遇到上述缺点 . 它不一定是那样 - 有使用Flash,Silverlight等实现安全的跨源连接的解决方法 - 但是大多数实现都不会这样做,因为它并不容易 .
例如,如果您依赖WebSocket进行跨源连接,则可以正常工作 . 但是,如果你然后在旧的浏览器或受干扰的防火墙/代理中运行并依赖Flash,比如说,作为你的后备,你会发现很难做同样的跨源连接 . 当然,除非你不关心安全 .
这意味着很难有一个统一的架构适用于本机和非本机连接,除非你准备投入相当多的工作或者使用已经做得很好的框架 . 在理想的架构中,您不会注意到连接是否是本机的;您的安全设置在两种情况下都有效;您的群集设置仍然有效;你的容量规划仍然有效;等等 .
它不像打开HTTP流那样简单,只需数据流动几分钟,几小时或更长时间就可以了 . 不同的客户端行为不同,您必须管理它 . 例如,某些客户端将缓冲数据,并且在满足某个阈值之前不会将其释放到应用程序 . 更糟糕的是,在连接关闭之前,有些人不会将数据传递给应用程序 .
因此,如果您向客户端发送多条消息,则可能是客户端应用程序在收到50条消息之前不会接收数据,例如 . 那不是太实时 .
虽然当WebSocket不可用时,HTTP流式传输可能是一种可行的选择,但它并不是万能药 . 在现实世界的条件下,需要很好地理解在Web的荒地中以健壮的方式工作 .
还有一件事没人提到,所以我会提出来的 .
WebSocket协议旨在成为更高级别协议的传输层 . 虽然您可以直接通过WebSocket连接发送JSON消息或什么不是,但它也可以携带标准或自定义协议 .
例如,您可以通过WebSocket执行AMQP或XMPP,就像人们已经做过的那样 . 因此,客户端可以从AMQP代理接收消息,就好像它直接连接到代理本身(在某些情况下它是) .
或者,如果您的现有服务器具有某些自定义协议,则可以通过WebSocket传输该服务器,从而将该后端服务器扩展到Web . 通常,已锁定在企业中的现有应用程序可以使用WebSocket扩展其范围,而无需更改任何后端基础结构 .
(当然,您希望能够安全地执行所有操作,因此请与供应商或WebSocket提供商联系 . )
有些人将WebSocket称为Web的TCP . 因为就像TCP传输更高级别的协议一样,WebSocket也是如此,但其方式与Web基础架构兼容 .
因此,尽管通过WebSocket直接发送JSON(或其他)消息总是可行的,但也应考虑现有协议 . 因为对于你想要做的很多事情,可能已经有一个协议已经被认为是这样做的 .
这是一个很好的问题,答案都非常丰富!
(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和业务逻辑时,往往不得不关心他们不应该关注的事情 - 他们不应该关注底层的沟通 .
HTTP将客户端与服务器之间的连接数限制为2(尽管可以通过使用子域来缓解这种情况),并且已知IE已经急切地强制执行此操作 . Firefox和Chrome允许更多(虽然我不记得我的头脑究竟有多少) . 这可能看起来不是一个大问题,但如果您经常使用1个连接进行实时更新,则所有其他请求都必须通过其他HTTP连接进行瓶颈 . 而且客户端有更多开放连接的问题会给服务器带来更多负担 .
WebSockets是基于TCP的协议,因此不受此HTTP级连接限制(但当然,浏览器支持不统一) .