Recently, we have had some issues where one script or website would cause an Apache child process to consume all of a server’s RAM. This eventually led to memory swapping and a kernel panic if left for a matter of minutes. We initially had set our eyes on RLimitMem, but quickly discovered that it only limits processes spawned by Apache children (such as PHP). So, in order to solve this problem, we stumbled on a great solution using an unexpected Apache module: mod_perl.
There is a perl module called Apache2::Resource (or Apache::Resource for those of you still using Apache 1.x) which allows resource throttling on a per process level. Not only can you limit memory usage, but CPU and other system resource limits are available as well (for a full list, consult your disto’s setrlimit man page). This module should be installed by default on most RHEL systems.
On CentOS 5, you will need to edit the /etc/httpd/conf.d/perl.conf file and add these lines below the LoadModule setting:
PerlSetEnv PERL_RLIMIT_AS 525
The RLIMIT_AS sets the soft and hard address space limits (in MBs) per Apache process. If only one value is set (like above), it sets the hard and soft limits to be the same. You could also specify them in the S:H format:
PerlSetEnv PERL_RLIMIT_AS 450:525
The above sets the soft limit to be 450MB and the hard limit to be 525MB. Please note that the RLIMIT_AS specifies virtual memory, not physical memory. Setting it too low can cause your web server to stop working due to Apache processes being killed off too early. You will be able to tell pretty quickly by trying to load a site and looking at the error log. Don’t be scared when you see ” [notice] child pid ### exit signal Segmentation fault (11)”. This is just the module killing processes.
Also note that 64bit apache/httpd processes will consume much more RAM than 32bit ones. We have seen numbers as high as 4-5x more, so set your limits accordingly. As always, please feel free to post any comments and questions, we’re more than happy to help!