12

Sec 8.1.2.2 Pipelining says:

"A server MUST send its responses to requests in the same order that the requests were received".

So, I thought, if I send out multiple AJAX requests from my browser, they will still be processed in the order in which they were received by the server.

But then, I was reading this post from Alex Maccaw, where he states :

"The last issue is with Ajax requests that get sent out in parallel. If a user creates a record, and then immediately updates the same record, two Ajax requests will be sent out at the same time, a POST and a PUT. However, if the server processes the 'update' request before the 'create' one, it'll freak out. It has no idea what record needs updating, as the record hasn't been created yet.

The solution to this is to pipeline Ajax requests, transmitting them serially. Spine does this by default, queuing up POST, PUT and DELETE Ajax requests so they're sent one at a time. The next request sent only after the previous one has returned successfully."

So, how can I programmatically create the scenario that Alex Maccaw mentions ?

2020
  • 2,821
  • 2
  • 23
  • 40

3 Answers3

12

I think in short, the answer to your question is "yes".

HTTP 1.1 does not forbid opening multiple TCP connections to the same server (in fact it recommends two), and all modern browsers do so (in fact, most do six or more). See Max parallel http connections in a browser? . A request-response cycle can be going on on each of those connections, and some of the request-response cycles can be much faster than others, for various reasons. Network congestion, complexity of the request, speed of and load on the particular "worker" your request is processed by, etc. This means that a request-response cycle for a request started later could easily finish sooner than a cycle for a request started earlier.

"A server MUST send its responses to requests in the same order that the requests were received".

This statement solely applies to pipelining multiple http requests, i.e. sending multiple requests over one TCP connection, without waiting for a response for each request. It does not apply to opening multiple TCP connections to the same server.

Normally, you have only one request per tcp connection going on at the same time. The client waits for response, and when it gets response, perhaps reuses the connection for a new request. Thus, as far as regular (non-pipelined) http is concerned, there isn't even a concept of "order of responses", because there's only a single request-response cycle going on on a TCP connection.

With pipelining, multiple http requests are fired of on one TCP connection. It's important to get the responses back in order, because that's the way responses are matched to their original requests. (Matching responses to requests could have been done differently, for example by providing a hash of the full request on each response or so, but that's beside the point).

Also, it's good to know that (default) support for HTTP pipelining is not broad. Chromium project is reluctant about enabling it: https://insouciant.org/tech/status-of-http-pipelining-in-chromium/ . Firefox still doesn't have it enabled either. https://bugzilla.mozilla.org/show_bug.cgi?id=264354

Apple on the other hand has enabled support for it in safari on IOS5, probably because request-response latency on mobile is a bigger problem. http://www.guypo.com/mobile/ios5-top10-performance-changes/ Android stock browser does too. At least the pre-Chrome version. http://www.guypo.com/mobile/http-pipelining-big-in-mobile/

Alex Maccaw wrote in the post about Spine you cite:

The solution to this is to pipeline Ajax requests, transmitting them serially.

I think the term pipeline is somewhat confusing in this context. First of all, the "pipelining" that Spine does is something wholly different than the possibility of pipelining requests in HTTP. Secondly, I think I'd call this particular feature of Spine request queuing. Spine queues requests, and processes the items in the queue in order they were added.

In general, I think the term "pipelining" is best used for when things are made purposively faster, while "queuing" is best used when making things purposively slower (to prevent race conditions, or to lighten load on the processor of the queued items, for example).

Community
  • 1
  • 1
Myrne Stol
  • 11,222
  • 4
  • 40
  • 48
  • You are right in that Pipelining and Persistent connections are different things. And persistent connections may or may not support pipelining. – 2020 Apr 30 '13 at 01:00
  • I am now confused which one to select as the Answer ! @Jon was the first to respond and his response cleared up things for me, but you have put in a lot of effort to clear up and summarize the whole thing ! – 2020 Apr 30 '13 at 16:46
1

They will not be handled synchronously unless the WebServer only has 1 thread to handle the requests which may only happen intentionally (possibly under a dev environment). Most of the time the Web server has hundreds of threads available to process requests as they come in and as 1 request may take longer than another, the responses can come back out of order. This is why it is called A(asynchronous)JAX.

1 request could take a full second to respond, while request 2 and 3 take 25ms to respond, thus the 1st request response comes in after both the 2nd and 3rd requests.

You can force a synchronous cycle but at the cost of everything stopping until the request is returned and processed, (Even JS loading spinners would stop).

See this article on forcing synchronous (SJAX) requests. http://www.hunlock.com/blogs/Snippets:_Synchronous_AJAX

justadevguy
  • 31
  • 1
  • 4
  • So, What do you say is the meaning of this statement in Sec 8.1.2.2 Pipelining : "A server MUST send its responses to requests in the same order that the requests were received" ? – 2020 Apr 29 '13 at 22:34
  • The statement about pipelining solely applies to pipelining multiple http requests, i.e. doing multiple request using one tcp connection, without waiting for a response for each request. It does not apply to opening multiple tcp connections to the same server. See for example: http://stackoverflow.com/questions/985431/max-parallel-http-connections-in-a-browser – Myrne Stol Apr 29 '13 at 23:44
1

RFC 2616 uses the term "pipelining" to refer to this:

  • HTTP requests and responses can be pipelined on a connection. Pipelining allows a client to make multiple requests without waiting for each response, allowing a single TCP connection to be used much more efficiently, with much lower elapsed time.

So pipelining here means using a persistent HTTP connection to make multiple requests. This is functionality that has to be supported by the browser, and currently it is either unsupported or off by default for pretty much every browser. So right now, when you make a number of plain AJAX requests there is always the possibility that responses will return out of order.

Most of the time this is not a problem. When it is, you can take appropriate measures to "pipeline" the requests manually; they still go out on separate connections, but your code is engineered to wait until a pending request has completed before issuing the next one. In the article you link to, this functionality is built into Spine.

SiHa
  • 7,830
  • 13
  • 34
  • 43
Jon
  • 428,835
  • 81
  • 738
  • 806
  • 1
    So, what is the basis on which a AJAX request determines if it should use a different connection or re-use the existing connection ? From what you say, it seems, if pipelining is Enabled, the AJAX requests would be sent on the SAME connection (and hence give a 'slower' feel), whereas when it is disabled each AJAX request could be sent on a different connection and hence receive out-of-order responses (and hence give a 'faster' feel) ! So, pipelining seems to achieve efficient use of TCP connection at the cost of application responsiveness. Pls correct me if I am wrong. – 2020 Apr 29 '13 at 23:02
  • @vendhan: You aren't wrong. :-) HTTP pipelining is mostly a tool to conserve server resources, that's IMHO the most relevant viewpoint. On the client side, when you need serialization you simply enforce it with code by withholding new requests. – Jon Apr 29 '13 at 23:05
  • Great ! Can you please shed light on (if there are) any other variables, other than Pipelining enabled/disabled, that would determine if a AJAX request should be sent on an existing connection or should use a new connection ? – 2020 Apr 29 '13 at 23:09
  • 1
    @vendhan: Using an existing connection is the definition of pipelining, so no other variables. It's just two ways to describe the same thing. – Jon Apr 29 '13 at 23:24
  • +1 ! An practitioner's explanation is always clearer than the Spec ! – 2020 Apr 29 '13 at 23:40
  • Pipelining is NOT the same as reusing the same connection. It's only pipelining if multiple requests are send over the same connection before a response to the earliest one is received. HTTP allows reusing of TCP connection with simple request-response cycle. – Myrne Stol Apr 29 '13 at 23:59
  • @MerynStol: That's true, but the context of this discussion is sending multiple requests without waiting for each response in turn so I feel it's implied. – Jon Apr 30 '13 at 08:25
  • 1
    Jon A little while after I posted this I realized that my comment may come across as a pointing out a mistake, while my intend was merely to clarify, since @vendhan seemed not to have a good grasp on the material in general. The danger of late-night commenting on stack overflow. ;) – Myrne Stol Apr 30 '13 at 10:59
  • @MerynStol: No worries, it's always good to clarify things. I appreciate your taking the time to do it. – Jon Apr 30 '13 at 11:02