12

Sec 8.1.2.2 Pipelining说:

“服务器必须以与接收请求相同的顺序发送对请求的响应”。

所以,我想,如果我从浏览器发出多个 AJAX 请求,它们仍将按照服务器接收它们的顺序进行处理。

但是后来,我正在阅读 Alex Maccaw 的这篇文章,他说:

“最后一个问题是并行发送的 Ajax 请求。如果用户创建记录,然后立即更新同一记录,则会同时发送两个 Ajax 请求,一个 POST 和一个 PUT。但是,如果服务器在“创建”请求之前处理“更新”请求,它会吓坏的。它不知道需要更新什么记录,因为该记录还没有被创建。

对此的解决方案是将 Ajax 请求流水线化,以串行方式传输它们。默认情况下,Spine 会执行此操作,将 POST、PUT 和 DELETE Ajax 请求排队,以便一次发送一个。只有在前一个请求成功返回后才发送下一个请求。”

那么,如何以编程方式创建 Alex Maccaw 提到的场景?

4

3 回答 3

12

我认为简而言之,您的问题的答案是“是”。

HTTP 1.1 并没有禁止打开到同一个服务器的多个 TCP 连接(实际上它建议两个),并且所有现代浏览器都这样做(事实上,大多数都这样做六个或更多)。请参阅浏览器中的最大并行 http 连接数?. 请求-响应周期可以在这些连接中的每一个上进行,并且由于各种原因,某些请求-响应周期可能比其他周期快得多。网络拥塞、请求的复杂性、处理您的请求的特定“工作人员”的速度和负载等。这意味着稍后开始的请求的请求-响应周期可能比开始的请求周期更早完成早些时候。

“服务器必须以与接收请求相同的顺序发送对请求的响应”。

该语句仅适用于流水线化多个 http 请求,即通过一个 TCP 连接发送多个请求,而不等待每个请求的响应。它不适用于打开到同一服务器的多个 TCP 连接。

通常,每个 tcp 连接同时进行的只有一个请求。客户端等待响应,当它得到响应时,可能会重用连接以获取新请求。因此,就常规(非流水线)http 而言,甚至没有“响应顺序”的概念,因为 TCP 连接上只有一个请求-响应周期。

使用流水线,可以在一个 TCP 连接上触发多个 http 请求。让响应按顺序返回很重要,因为这是响应与原始请求匹配的方式。(对请求的匹配响应可能会以不同的方式完成,例如通过在每个响应左右提供完整请求的哈希值,但这不是重点)。

此外,很高兴知道(默认)对 HTTP 管道的支持并不广泛。Chromium 项目不愿意启用它:https ://insouciant.org/tech/status-of-http-pipelining-in-chromium/ 。Firefox 仍然没有启用它。https://bugzilla.mozilla.org/show_bug.cgi?id=264354

另一方面,Apple 已经在 IOS5 的 safari 中启用了对它的支持,可能是因为移动设备上的请求-响应延迟是一个更大的问题。http://www.guypo.com/mobile/ios5-top10-performance-changes/ Android 股票浏览器也是如此。至少是 Chrome 之前的版本。http://www.guypo.com/mobile/http-pipelining-big-in-mobile/

Alex Maccaw 在您引用的关于 Spine 的帖子中写道:

对此的解决方案是将 Ajax 请求流水线化,以串行方式传输它们。

我认为在这种情况下,术语管道有点令人困惑。首先,Spine 所做的“流水线”与 HTTP 中的流水线请求完全不同。其次,我认为我将这个特殊的特性称为 Spine 请求队列。Spine 对请求进行排队,并按添加顺序处理队列中的项目。

一般来说,我认为术语“流水线”最适合用于故意使事情变得更快,而“排队”最适合用于故意使事情变慢(以防止竞争条件,或减轻排队项目处理器的负载, 例如)。

于 2013-04-29T23:54:45.093 回答
1

它们不会被同步处理,除非 WebServer 只有 1 个线程来处理可能只是有意发生的请求(可能在开发环境下)。大多数情况下,Web 服务器有数百个线程可用于处理传入的请求,并且由于一个请求可能比另一个请求花费更长的时间,因此响应可能会乱序返回。这就是它被称为 A(asynchronous)JAX 的原因。

1 个请求可能需要一整秒才能响应,而请求 2 和 3 需要 25ms 才能响应,因此第一个请求响应在第二个和第三个请求之后出现。

您可以强制同步循环,但代价是一切都停止,直到请求被返回和处理(即使是 JS 加载微调器也会停止)。

请参阅这篇关于强制同步 (SJAX) 请求的文章。 http://www.hunlock.com/blogs/Snippets:_Synchronous_AJAX

于 2013-04-29T21:23:50.607 回答
1

RFC 2616 使用术语“流水线”来指代:

  • HTTP 请求和响应可以在连接上进行管道传输。流水线允许客户端在不等待每个响应的情况下发出多个请求,从而可以更有效地使用单个 TCP 连接,并且花费的时间要短得多。

所以这里的流水线意味着使用持久的 HTTP 连接来发出多个请求。这是浏览器必须支持的功能,目前几乎所有浏览器都不支持或默认关闭。所以现在,当你发出一些普通的 AJAX 请求时,总是有可能返回乱序的响应。

大多数时候这不是问题。如果是,您可以采取适当的措施来手动“管道”请求;它们仍然通过单独的连接出去,但是您的代码被设计为等到待处理的请求完成后再发出下一个请求。在您链接到的文章中,此功能内置于 Spine。

于 2013-04-29T22:48:17.710 回答