Setting Apache web server up on linux to handle overload/'digg effect' more gracefully

The problem:

All default apache installations I have seen allow it to create far too many processes so when lots of traffic comes along apache makes about 200 processes, memory is fine but each request only gets about 0.3-5% of the available cputime. This means it takes too long to process the request causing timeouts, refreshes and even more load. This can continue untill the content is taken down with the user feeling that done have enough hardware to handle the traffic, or the machine eats through all the swap trying to handle the load and panics.

The solution:

I have sucesfully combated this issue on my servers by setting up the preform MPM limits more effectively. In my experience this causes very few (no more than 16 in my case) apache threads to be created meaning each request has a large share of the CPU time - and is dealt with much more quickly - before the requesting browser gives up! Requests that come along while the server is busy are queued up and dealt with as soon as more resources become available, this normally is before the requesting browser has given up. In extreme cases (in my case a lot of traffic hitting an unoptimised wordpress weblog) some requests are dropped however the bulk of the requests were serviced within 4 seconds and only about 1% of requests failed to go through.

Implementation:

I am not responsible for anything that may occur from following these instructions.

Locate your apache config file, in my case this was /etc/apache2/apache2.conf or /etc/httpd/conf/httpd.conf on this centos box. Then find the section related to the preform MPM.

Reduce all the values considerably and increase the MaxRequestsPerChild. The numbers that work for you will depend on your setup, I suggest you have a play around to see what works best for you. I am pasting my own section below, these settings work nicely for me on a dual pentium 1.1ghz machine with 1.5 gb of ram (the machine this article is hosted on)

<IfModule prefork.c>
StartServers 2
MinSpareServers 3
MaxSpareServers 5
ServerLimit 16
MaxClients 16
MaxRequestsPerChild 400000
</IfModule>

Gotchas and finishing up:

It'd be ironic if this got on the front page and my server went down, but be mindfull that this site is hosted on an adsl connection in the UK, I expect my router is likely to die before this server tho! Some workloads are too high for this technique to be sensible, in those cases I suggest using varnish http accelerator or squid configured as a reverse proxy.

If you have found this article interesting or usefull please remember to digg it!