Sunday, July 02, 2006

AJAX done well can reduce server load and bandwidth, but I've seen a lot of people jumping on the AJAX bandwagon who don't really consider what the impact is on the back-end.

Done badly, AJAX can bring a server to its knees.

If you are writing an AJAX application and you have never heard of  "/dev/poll" or the "thundering herd problem" then you really ought to smarten yourself up by reading this, and if you don't understand that post then read the rest of this one..

The issue in a nutshell relates to one of the great dirty secrets of the Internet and the operating system wars.

When the Internet burst forward, every man and his operating system provider built a web-server on top of the file IO handling of their current OS kernels. These kernels having being optimised generally for word-processing, volume, speed, but not lots of tiny little requests in parallel.

"Lots of tiny little requests in parallel" - sound like anything you know?

Only one company got it right the first time, and that was Sun, because Solaris 2.7+ had poll() and /dev/poll. This is one of the reasons people used to rave about the performance of Sun and Solaris.

Windows let you handle a whole maximum of 64 connections in one go, to do anything better, you had to perform your own magic.

The majority of the operating systems were awful at handling the one thing that web-servers need to perform well, and that is reading and writing data from a lot of simultaneous connections, or more specifically, knowing when to read and write.

Every time you use a XMLHttpRequest object in your AJAX code, you can, if you don't know what you are doing, create a new TCP/IP connection on the remote server.

The remote server may still have the previous connections in a wait state of some kind. These can build up over time and all of a sudden your server gets sluggish or starts rejecting connections. This can be less of a /dev/poll issue and more of a lack of system resources - but the cause is the same.

bad_ajax_scaleability.png

Oh The Humanity!

As a general rule, naively configured servers start to have a hard time at a few hundred connections - after that you start to degrade rapidly, the scalability curve can be brutal.

poll.png

Here We Go Again!

If the above makes no sense to you because all you do is front-end and want to AJAXify a site - then here are some general rules.

#1) Don't try heavy AJAX on a server that does not support HTTP1.1.

The killer feature of HTTP1.1 is that it implicitly uses one socket connection for multiple http requests. So your entire impact on a server can be one connection per user. This behavior is explicit in HTTP1.0 via specifying the KeepAlive header.

Almost all modern servers use HTTP1.1, but its nice to make sure.

#2) request.setRequestHeader("Connection", "close");

Don't use it unless you know what you are doing. This will force a close of the connection. This is fine if you just make one request. But if you have a large number of requests per user session (auto completion for example) then your service can fall over after a few minutes of just one user typing away.

On modern browsers, XMLHttpRequest  is clever and even if you create and destroy your XMLHttpRequest connection object, it will still keep and reuse your current connection to the server.

#3) Hire someone who knows what they are doing

Humans suffer permanent damage when accelerated above 20G... stay with me on this one..

If you want to stick the AJAX rocket onto your server, maybe you need a rocket scientist?

Get someone who knows how to make a server sing, especially if you are about to increase the number of requests its going to get. If you can find someone who installed the /dev/epoll linux kernel patch when it first came out, then you may be onto a winner.

If you don't know what you are really doing, at least use an AJAX library that is written by someone who does.

 

Sunday, July 02, 2006 3:38:12 PM (AUS Eastern Standard Time, UTC+10:00)  #    Comments [13]Tracked by:
"The Digg Effect" (James Mc Parlane's Blog) [Trackback]