是否可以通过HTTP接收无序响应?

时间:2013-04-29 20:57:55

标签: ajax http web-applications asynchronous

Sec 8.1.2.2 Pipelining说:

  

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

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

然而,我正在阅读Alex Maccaw的post,他说:

  

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

     

解决方案是管道Ajax请求,以串行方式传输它们。脊柱    默认情况下这样做,排队POST,PUT和DELETE Ajax请求,以便它们被发送一个    一次。只有在前一个请求成功返回后才发送下一个请求。“

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

3 个答案:

答案 0 :(得分:9)

我想简而言之,你的问题的答案是肯定的。

HTTP 1.1不禁止打开到同一服务器的多个TCP连接(事实上它推荐两个),并且所有现代浏览器都这样做(实际上,大多数都是六个或更多)。见Max parallel http connections in a browser?。由于各种原因,可以在每个连接上进行请求 - 响应循环,并且一些请求 - 响应循环可以比其他循环快得多。网络拥塞,请求的复杂性,处理请求的特定“工作者”的速度和负载等等。这意味着稍后启动的请求的请求 - 响应周期可能比请求开始的周期更快地完成早。

  

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

此声明仅适用于流水线化多个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对请求进行排队,并按顺序处理队列中的项目。

一般来说,我认为“流水线”这个术语最适合用于有目的地加快速度的事情,而“排队”最好用于使事情有目的地变慢(防止竞争条件,或减轻处理器的负担)排队的项目,例如)。

答案 1 :(得分:1)

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

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

您可以强制执行同步循环,但是在返回和处理请求之前停止所有操作(甚至JS加载微调器都会停止)。

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

答案 2 :(得分:1)

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

  
      
  • HTTP请求和响应可以在连接上进行流水线操作。       流水线技术允许客户端无需多次请求       等待每个响应,允许单个TCP连接       使用效率更高,使用时间更短。
  •   

因此,在此处使用流水线意味着using a persistent HTTP connection可以发出多个请求。这是浏览器必须支持的功能,目前它几乎不支持或默认关闭每个浏览器。所以现在,当你提出一些简单的AJAX请求时,总是有可能响应将无序返回。

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