It started one day when I was using the WordPress admin interface and kept getting HTTP 500 errors. A few refreshes, and everything would load again. I vaguely remembered encountering intermittent HTTP 500 errors previously before, but this time, it seemed to occur quite frequently, so I went to investigate.
I thought it was quite curious that after several seconds of refreshing, the page would load. Checking top showed that after hitting the admin interface, the server would have no free memory, then several seconds later, the memory would be freed. Sounds like this was due to KeepAlive. In my original configuration, KeepAliveTimeout was set to 15 seconds. So that’s the problem. Next question is, should I lower the KeepAliveTimeout, or just turn it off?
It turns out there’s quite a bit of discussion on this question. KeepAlive works alongside HTTP 1.1, which specifies persistent connections so that the browser keeps the same connection to the server to load other elements on the page. However, the reality is that modern browsers use parallel (concurrent) connections to the server, which is faster than loading page elements sequentially. This is especially when webpages are complex and contain lots of rich media. This is not to say that KeepAlive is outdated. It still has its use, but the decision to use it is not so straightforward.
To decide whether or not to use KeepAlive, consider the CPU/RAM limits of the server. On a server which is limited by RAM, KeepAlive should be off so as to quickly free up RAM for the server to continue serving the next request, instead of holding on and hogging available memory. Conversely, turning off KeepAlive would increase CPU usage from the overhead of creating new processes and opening sockets.
In this case, since the admin interface would use so much RAM, I decided to turn off KeepAlive.
However, I was still getting errors when performing some tasks, such as uploading a bunch a photos. With a fresh cup of coffee, I sat down and investigated further.
The first place to check was the syslog, which showed suhosin alerting me that WordPress admin.php was trying to increase the memory limit. The alert looks like this:
Jun 25 08:57:07 vps3 suhosin: ALERT - script tried to increase memory_limit to 268435456 bytes which is above the allowed value (attacker 'x.x.x.x', file '/xxx/wp-admin/admin.php', line 109)
Now, increasing the allowed limit is not a big problem. On Debian, the config file is located at /etc/php5/apache2/conf.d/suhosin.ini. Just edit the file and uncomment (or add) the line
suhosin.memory_limit = 256M
The bigger problem that follows is that with 256MB of memory usage, does the server have enough RAM to cope? Trying to upload multiple files answered that question. The server ran out of memory, and on my SSH terminal, I couldn’t even run top.
A quick reboot of the server, and I checked my Apache configuration. I don’t know when I last edited it, but I immediately spotted the problem.
<IfModule mpm_prefork_module> StartServers 4 MinSpareServers 4 MaxSpareServers 8 MaxClients 48 MaxRequestsPerChild 0 </IfModule>
The MaxClients is set to high. Assuming a (very) conservative 20MB per PHP process, 48 clients would require 960MB of RAM. If you add on MySQL and other services running on the server which has 1GB of RAM, this will clearly cause the server to run out of memory. Even worse, the WordPress admin interface requires 256MB of RAM. If I calculate MaxClients based on 256MB per process, I can only have a maximum of…… 3. That doesn’t sound very reasonable, especially when visitors hitting the WordPress blogs themselves would use far less. Yet if I increase MaxClients, then using the admin interface would cause the server to run out of memory! This is especially when you upload multiple files, which create multiple connections to the server (and each requiring 256MB). A quick Google search found many users encountering this problem, and I’m not surprised now.
Thankfully, after many complaints, WordPress added the ability to set the memory limit (it was previously hardcoded). Although they don’t specify what the minimum memory limit is for the admin interface to remain usable, 128MB seems to work fine. So I added this line to my wp-config.php:
With this new limit, I can re-adjust my Apache configuration. I prefer a more conservative setting, so I now set MaxClients to 6, which means at its peak, Apache will use up 768MB of memory, comfortable for my server without compromising on the performance of other services.
So far so good!