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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/12555043/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-23 10:41:44  来源:igfitidea点击:

My Understanding of HTTP Polling, Long Polling, HTTP Streaming and WebSockets

javascriptweb-applicationswebsocketcomethttp-streaming

提问by Software Guy

I have read many posts on SO and the web regarding the keywords in my question title and learned a lot from them. Some of the questions I read are related to specific implementation challenges while others focus on general concepts. I just want to make sure I understood all of the concepts and the reasoning why technology X was invented over technology Y and so on. So here goes:

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

Http Polling:Basically AJAX, using XmlHttpRequest.

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

Http Long Polling:AJAX but the server holds on to the response unless the server has an update, as soon as the server has an update, it sends it and then the client can send another request. Disadvantage is the additional header data that needs to be sent back and forth causing additional overhead.

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

Http Streaming:Similar to long polling but the server responds with a header with "Transfer Encoding: chunked" and hence we do not need to initiate a new request every time the server sends some data (and hence save the additional header overhead). The drawback here is that we have to "understand" and figure out the structure of the data to distinguish between multiple chunks sent by the server.

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

Java Applet, Flash, Silverlight:They provide the ability to connect to socket servers over tcp/ip but since they are plugins, developers don't want to depend on them.

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

WebSockets:they are the new API which tries to address the short comings of above methods in the following manner:

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

  • The only advantage of WebSockets over plugins like Java Applets, Flash or Silverlight is that WebSockets are natively built into browsers and does not rely on plugins.
  • The only advantage of WebSockets over http streaming is that you don't have to make an effort to "understand" and parse the data received.
  • The only advantage of WebSockets over Long Polling is that of elimination of extra headers size & opening and closing of socket connection for request.
  • 与 Java Applets、Flash 或 Silverlight 等插件相比,WebSockets 的唯一优势是 WebSockets 原生内置于浏览器中,不依赖于插件。
  • WebSockets 相对于 http 流的唯一优势是您不必努力“理解”和解析接收到的数据。
  • 与长轮询相比,WebSockets 的唯一优势是消除了额外的标头大小以及为请求打开和关闭套接字连接。

Are there any other significant differences that I am missing? I'm sorry if I am re-asking or combining many of the questions already on SO into a single question, but I just want to make perfect sense out of all the info that is out there on SO and the web regarding these concepts.

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

Thanks!

谢谢!

采纳答案by kanaka

There are more differences than the ones you have identified.

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

Duplex/directional:

双工/定向:

  • Uni-directional: HTTP poll, long poll, streaming.
  • Bi-direcitonal: WebSockets, plugin networking
  • 单向:HTTP 轮询、长轮询、流媒体。
  • 双向:WebSockets、插件网络

In order of increasing latency (approximate):

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

  • WebSockets
  • Plugin networking
  • HTTP streaming
  • HTTP long-poll
  • HTTP polling
  • 网络套接字
  • 插件网络
  • HTTP 流媒体
  • HTTP 长轮询
  • HTTP 轮询

CORS (cross-origin support):

CORS(跨域支持):

  • WebSockets: yes
  • Plugin networking: Flash via policy request (not sure about others)
  • HTTP * (some recent support)
  • WebSockets:是的
  • 插件网络:通过策略请求 Flash(不确定其他人)
  • HTTP *(最近的一些支持)

Native binary data (typed arrays, blobs):

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

  • WebSockets: yes
  • Plugin networking: not with Flash (requires URL encoding across ExternalInterface)
  • HTTP *: recent proposal to enable binary type support
  • WebSockets:是的
  • 插件网络:不使用 Flash(需要跨 ExternalInterface 进行 URL 编码)
  • HTTP *:最近提议启用二进制类型支持

Bandwidth in decreasing efficiency:

降低效率的带宽:

  • Plugin networking: Flash sockets are raw except for initial policy request
  • WebSockets: connection setup handshake and a few bytes per frame
  • HTTP streaming (re-use of server connection)
  • HTTP long-poll: connection for every message
  • HTTP poll: connection for every message + no data messages
  • 插件网络:Flash 套接字是原始的,除了初始策略请求
  • WebSockets:连接设置握手和每帧几个字节
  • HTTP 流(重用服务器连接)
  • HTTP 长轮询:每条消息的连接
  • HTTP 轮询:每条消息的连接 + 无数据消息

Mobile device support:

移动设备支持:

  • WebSocket: iOS 4.2 and up. Some Android via Flash emulation or using Firefox for Androidor Google Chrome for Androidwhich both provide native WebSocket support.
  • Plugin networking: some Android. Not on iOS
  • HTTP *: mostly yes
  • WebSocket:iOS 4.2 及更高版本。一些 Android 通过 Flash 模拟或使用Firefox for AndroidGoogle Chrome for Android,它们都提供原生 WebSocket 支持。
  • 插件网络:一些Android。不在 iOS 上
  • HTTP *:大部分是

Javascript usage complexity (from simplest to most complicated). Admittedly complexity measures are somewhat subjective.

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

  • WebSockets
  • HTTP poll
  • Plugin networking
  • HTTP long poll, streaming
  • 网络套接字
  • HTTP 轮询
  • 插件网络
  • HTTP 长轮询,流式传输

Also note that there is a W3C proposal for standardizing HTTP streaming called Server-Sent Events. It is currently fairly early in it's evolution and is designed to provide a standard Javascript API with comparable simplicity to WebSockets.

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

回答by Robin Zimmermann

Some great answers from others that cover a lot of ground. Here's a little bit extra.

其他人的一些很好的答案涵盖了很多领域。这里有一点额外的。

The only advantage of WebSockets over plugins like Java Applets, Flash or Silverlight is that WebSockets are natively built into browsers and does not rely on plugins.

与 Java Applets、Flash 或 Silverlight 等插件相比,WebSockets 的唯一优势是 WebSockets 原生内置于浏览器中,不依赖于插件。

If by this you mean that you can use Java Applets, Flash, or Silverlight to establish a socket connection, then yes, that is possible. However you don't see that deployed in the real world too often because of the restrictions.

如果这意味着您可以使用 Java Applet、Flash 或 Silverlight 来建立套接字连接,那么是的,这是可能的。但是,由于限制,您不会经常在现实世界中看到它的部署。

For example, intermediaries can and do shutdown that traffic. The WebSocket standard was designed to be compatible with existing HTTP infrastructure and so is far less prone to being interfered with by intermediaries like firewalls and proxies.

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

Moreover, WebSocket can use port 80 and 443 without requiring dedicated ports, again thanks to the protocol design to be as compatible as possible with existing HTTP infrastructure.

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

Those socket alternatives (Java, Flash, and Silverlight) are difficult to use securely in a cross-origin architecture. Thus people often attempting to use them cross-origin will tolerate the insecurities rather than go to the effort of doing it securely.

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

They can also require additional "non-standard" ports to be opened (something administrators are loathe to do) or policy files that need to be managed.

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

In short, using Java, Flash, or Silverlight for socket connectivity is problematic enough that you don't see it deployed in serious architectures too often. Flash and Java have had this capability for probably at least 10 years, and yet it's not prevalent.

简而言之,使用 Java、Flash 或 Silverlight 进行套接字连接的问题已经够大了,您不会经常看到它部署在严肃的体系结构中。Flash 和 Java 已经拥有这种能力至少 10 年了,但它并不普遍。

The WebSocket standard was able to start with a fresh approach, bearing those restrictions in mind, and hopefully having learned some lessons from them.

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

Some WebSocket implementations use Flash (or possibly Silverlight and/or Java) as their fallback when WebSocket connectivity cannot be established (such as when running in an old browser or when an intermediary interferes).

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

While some kind of fallback strategy for those situations is smart, even necessary, most of those that use Flash et al will suffer from the drawbacks described above. It doesn't have to be that way -- there are workarounds to achieve secure cross-origin capable connections using Flash, Silverlight, etc -- but most implementations won't do that because it's not easy.

虽然针对这些情况的某种回退策略是明智的,甚至是必要的,但大多数使用 Flash 等的策略都会受到上述缺点的影响。不一定要那样——有一些变通方法可以使用 Flash、Silverlight 等实现安全的跨域连接——但大多数实现不会这样做,因为这并不容易。

For example, if you rely on WebSocket for a cross-origin connection, that will work fine. But if you then run in an old browser or a firewall/proxy interfered and rely on Flash, say, as your fallback, you will find it difficult to do that same cross-origin connection. Unless you don't care about security, of course.

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

That means it's difficult have a single unified architecture that works for native and non-native connections, unless you're prepared to put in quite a bit of work or go with a framework that has done it well. In an ideal architecture, you wouldn't notice if the connections were native or not; your security settings would work in both cases; your clustering settings would still work; your capacity planning would still hold; and so on.

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

The only advantage of WebSockets over http streaming is that you don't have to make an effort to "understand" and parse the data received.

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

It's not as simple as opening up an HTTP stream and sitting back as your data flows for minutes, hours, or longer. Different clients behave differently and you have to manage that. For example some clients will buffer up the data and not release it to the application until some threshold is met. Even worse, some won't pass the data to the application until the connection is closed.

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

So if you're sending multiple messages down to the client, it's possible that the client application won't receive the data until 50 messages worth of data has been received, for example. That's not too real-time.

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

While HTTP streaming can be a viable alternative when WebSocket is not available, it is not a panacea. It needs a good understanding to work in a robust way out in the badlands of the Web in real-world conditions.

虽然当 WebSocket 不可用时,HTTP 流可能是一个可行的替代方案,但它不是万能药。在现实世界条件下的 Web 荒地中以稳健的方式工作需要很好的理解。

Are there any other significant differences that I am missing?

我还缺少其他任何显着差异吗?

There is one other thing that noone has mentioned yet, so I'll bring it up.

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

The WebSocket protocol was designed to a be a transport layer for higher-level protocols. While you can send JSON messages or what-not directly over a WebSocket connection, it can also carry standard or custom protocols.

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

For example, you could do AMQP or XMPP over WebSocket, as people have already done. So a client could receive messages from an AMQP broker as if it were connected directly to the broker itself (and in some cases it is).

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

Or if you have an existing server with some custom protocol, you can transport that over WebSocket, thus extending that back-end server to the Web. Often an existing application that has been locked in the enterprise can broaden it's reach using WebSocket, without having to change any of the back-end infrastructure.

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

(Naturally, you'd want to be able to do all that securely so check with the vendor or WebSocket provider.)

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

Some people have referred to WebSocket as TCP for the Web. Because just like TCP transports higher-level protocols, so does WebSocket, but in a way that's compatible with Web infrastructure.

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

So while sending JSON (or whatever) messages directly over WebSocket is always possible, one should also consider existing protocols. Because for many things you want to do, there's probably a protocol that's already been thought of to do it.

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

I'm sorry if I am re-asking or combining many of the questions already on SO into a single question, but I just want to make perfect sense out of all the info that is out there on SO and the web regarding these concepts.

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

This was a great question, and the answers have all been very informative!

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

回答by Robin Zimmermann

If I may ask one additional thing: I came across in an article somewhere that says that http streaming may also be cached by proxies while websockets are not. what does that mean?

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

(StackOverflow limits the size of comment responses, so I've had to answer here rather than inline.)

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

That's a good point. To understand this, think about a traditional HTTP scenario... Imagine a browser opened a web page, so it requests http://example.com, say. The server responds with HTTP that contains the HTML for the page. Then the browser sees that there are resources in the page, so it starts requesting the CSS files, JavaScript files, and images of course. They are all static files that will be the same for allclients requesting them.

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

Some proxies will cache static resources so that subsequent requests from other clients can get those static resources from the proxy, rather than having to go all the way back to the central web server to get them. This is caching, and it's a great strategy to offload requests and processing from your central services.

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

So client #1 requests http://example.com/images/logo.gif, say. That request goes through the proxy all the way to the central web server, which serves up logo.gif. As logo.gif passes through the proxy, the proxy will save that image and associate it with the address http://example.com/images/logo.gif.

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

When client #2 comes along and also requests http://example.com/images/logo.gif, the proxy can return the image and no communication is required back to the web server in the center. This gives a faster response to the end user, which is always great, but it also means that there is less load on the center. That can translate to reduced hardware costs, reduced networking costs, etc. So it's a good thing.

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

The problem arises when the logo.gif is updated on the web server. The proxy will continue to serve the old image unaware that there is a new image. This leads to a whole thing around expiry so that the proxy will only cache the image for a short time before it "expires" and the next request goes through the proxy to the web server, which then refreshes the proxy's cache. There are also more advanced solutions where a central server can push out to known caches, and so on, and things can get pretty sophisticated.

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

How does this tie in to your question?

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

You asked about HTTP streaming where the server is streaming HTTP to a client. But streaming HTTP is just like regular HTTP except you don't stop sending data. If a web server serves an image, it sends HTTP to the client that eventually ends: you've sent the whole image. And if you want to send data, it's exactly the same, but the server just sends for a really long time (like it's a massively gigantic image, say) or even never finishes.

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

From the proxy's point of view, it cannot distinguish between HTTP for a static resource like an image, or data from HTTP streaming. In both of those cases, the client made a request of the server. The proxy remembered that request and also the response. The next time that request comes in, the proxy serves up the same response.

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

So if your client made a request for stock prices, say, and got a response, then the next client may make the same request and get the cached data. Probably not what you want! If you request stock prices you want the latest data, right?

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

So it's a problem.

所以这是一个问题。

There are tricks and workarounds to handle problems like that, it is true. Obviously you can get HTTP streaming to work since it's it's in use today. It's all transparent to the end user, but the people who develop and maintain those architectures have to jump through hoops and pay a price. It results in over-complicated architectures, which means more maintenance, more hardware, more complexity, more cost. It also means developers often have to care about something they shouldn't have to when they should just be focussing on the application, GUI, and business logic -- they shouldn't have to be concerned about the underlying communication.

有一些技巧和解决方法可以处理这样的问题,这是真的。很明显,您可以使用 HTTP 流,因为它今天正在使用。这对最终用户来说都是透明的,但是开发和维护这些架构的人必须跳过障碍并付出代价。它导致架构过于复杂,这意味着需要更多的维护、更多的硬件、更多的复杂性、更多的成本。这也意味着开发人员通常不得不关心他们不应该关心的事情,而他们应该只关注应用程序、GUI 和业务逻辑——他们不应该关心底层通信。

回答by TheJuice

HTTP limits the number of connections a client can have with a server to 2 (although this can be mitigated by using subdomains) and IE has been known to enforce this eagerly. Firefox and Chrome allow more (although I can't remember of the top of my head exactly how many). This might not seem like a huge issue but if you are using 1 connection constantly for real-time updates, all other requests have to bottleneck through the other HTTP connection. And there is the matter of having more open connections from clients puts more load on the server.

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

WebSockets are a TCP-based protocol and as such don't suffer from this HTTP-level connection limit (but, of course, browser support is not uniform).

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