Years ago, I worked in a small group that occasionally needed technical information from a second group. I was young and naive, and believed that if a person said “yes, the proper setting for the frobnitz is 34.128″ then setting the frobnitz to 34.128 was the Right Thing To Do.
I quickly found out that some members of that group were more than happy to supply you with an answer to any question you asked, regardless of whether they knew the answer or not. And those guys would speak as authoritatively when spinning a tale from whole cloth as they would when providing information that actually intersected with reality.
The words “I don’t know” were not in their vocabulary.
Beyond a mistrust for anything these guys said, I also learned the importance of those three words. There’s no crime in not knowing the answer to every question. Since those days, I’ve tried to be clear with people when I didn’t know something. I’ve had many opportunities for clarity.
There are times though, when you assume you know how something works, but what’s in your head is slightly misaligned with reality.
Concurrent XHR Requests
I was giving a talk on Ajax programming recently. I wanted to show the audience how the XHR (XMLHttpRequest) object allowed multiple concurrent server requests.
To illustrate this, I wrote an example program that fired off five simultaneous XHR requests. These requests called a simple server script that waited for a client-specified number of seconds before returning a message back to the client.
The idea was to illustrate how XHR requests can return in a different order than they were sent out. To that end I gave each of the five requests a different delay value. These values were (in seconds) 4, 8, 20, 2, and 7.
The figure below shows the results of a test run.
The number to the left on each box is the order that request completed. The rest of the line shows the reponse from the server. The server message tells the time the server received the request, and the time it replied to the request.
Looking at the timings, is this the order you expected? Half of you are saying “of course you idiot!” The other half may be as confused as I was.
Why didn’t the two-second delay finish first? Why did the eight-second delay finish second? Because the browser only allows two HTTP connections to a server at any one time.
Since the requests are fired off from top to bottom, the four-second and eight-second requests grab those two available connections. The other three requests sit in an internal queue on the browser, waiting for one of those first two requests to finish. Look at the time the server replied to the four-second delay, then look at the time the server received the 20-second delay.
So why are only two connections allowed at a time? Because the browser is trying to be standards compliant. In this case, the standard is RFC 2616, “Hypertext Transfer Protocol
– HTTP/1.1″. Section 8.1.4, covering “Persistent Connections / Practical Considerations”, states:
“Clients that use persistent connections SHOULD limit the number of simultaneous connections that they maintain to a given server. A single-user client SHOULD NOT maintain more than 2 connections with any server or proxy. A proxy SHOULD use up to 2*N connections to another server or proxy, where N is the number of simultaneously active users. These guidelines are intended to improve HTTP response times and avoid congestion.”
Both Firefox and Microsoft IE honor this limitation. Since your XHR requests are going to the same server, this limits you to two connections at a time.
Does This Matter?
For many applications, this is no big deal. If your app only makes requests based on occasional user input, then you may never see a problem. But if your application is doing a lot of “background work” — predictive caching for example, you may be trying to access the server quite a bit. You need to keep the “two-connection limit” rule in mind when you build your apps.
Here are some ideas for managing those two-connections. These ideas don’t include tricks that don’t use XHR (SCRIPT tags and IFRAMES).
- Bundle multiple requests together. Write code on the server that unbundles the requests, gathers the responses,and then sends them back as a group.
- Set client-side timeouts for requests. If the server takes too long to respond, abort the request and free up the
- Avoid bottlenecks with smart coding. If you’re making requests to the server as the user types into a text box
(like Google Suggest) send requests based on a timer, not on every keystroke.
I’m sure you can think of others. I’d like to hear them.
Since the “two-connection rule” is a browser limitation, you can modify it if you choose to. Of course you can’t control other people’s browser settings, but if you want to play with your own settings, here’s how.
For Microsoft IE, you’ll have to modify a Windows Registry entry called MaxConnectionsPerServer. Microsoft has a knowledgebase article (“WinInet limits connections per server”) that shows you how.
For Firefox, just type “about:config” in the address bar and hit enter. Then type “connections” into the Filter field. The setting your looking for is network.http.max-persistent-connections-per-server. You can read more about this setting here.
In Opera, you can change the value through the Preferences dialog box. Look under Advanced -> Network.
And now I know something that I didn’t know that I didn’t know.