Jesse's Software Engineering Blog
Apache Prefork MPM MaxClients
Apache2 comes with two different multi processing modules (MPM): Prefork MPM and Worker MPM. Usually when installing Apache via a Linux package manager, unless specifically specified, Apache will be operating with Prefork MPM. Prefork MPM uses multiple child processes, with one thread each, and each process handles one connection at a time. Worker MPM uses multiple child processes, with many threads each, and each thread handles one connection at a time. In general, Worker MPM has a lower memory footprint and is more efficient, but is not thread safe, so running PHP, at least via mod_php, cannot be done with Worker MPM. Although with the release of PHP-FPM (FastCGI Process Manager) as an alternative to PHP FastCGI, we are no longer restricted to running Apache/PHP with the Prefork MPM.
There are numerous Prefork MPM configurations that can be changed to fine tune how much memory Apache will use. Before beginning, verify that Apache is using the Prefork MPM:
> httpd -V | grep MPM Server MPM: Prefork -D APACHE_MPM_DIR="server/mpm/prefork"
Process Memory Usage
Before being able to determine how much memory should be allotted to Apache processes, determine how much memory is being used on the server:
> top PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND 6726 mongod 20 0 545m 36m 4160 S 0.7 7.4 266:46.06 mongod 25608 root 20 0 15028 1244 948 R 0.3 0.2 0:00.03 top ...
The RES value will show how much memory the processes are using, with %MEM being the overall percentage of memory used. You need to be sure not to take too much memory from the server as to disrupt the other processes. In the above output the only service with significant memory usage, mongod, is using 36MB. So if the server has 512MB of RAM, at most that Apache can use is 476MB. However, it is important to leave extra memory available for the Linux kernel and various other processes. I will leave 10% of the memory for mongod, and another 5% for the kernel and other processes, allowing for 435MB to be used by Apache.
Apache Memory Usage
Next determine how much memory each Apache process is using:
> top -bn 1 | grep httpd PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND 15347 apache 20 0 251m 34m 22m S 0.0 8.2 0:04.24 httpd 15348 apache 20 0 241m 22m 15m S 0.0 6.1 0:04.96 httpd ...
The above output shows how much memory each Apache process is using, under the RES column. Notice they will not all be the same, so when determining the process size to use for memory usage calculations be sure to go above the average, but not necessarily the max value. Also important, as the complexity of the content being served increases so will the Apache process memory requirement making this value something to be periodically checked.
Now that the available memory, as well as the Apache process memory requirement, has been determined we are able to determine how many processes we should allow Apache’s Prefork MPM:
435MB free memory / 30MB per process = ~14 processes (rounded down)
Remember since Prefork MPM handles one connection per process, the Apache server will only be able to handle 14 simultaneous connections at a time. To configure Apache, open the httpd.conf file and update the prefork.c directive’s values:
<IfModule prefork.c> StartServers 5 MinSpareServers 5 MaxSpareServers 10 ServerLimit 14 MaxClients 14 MaxRequestsPerChild 500 </IfModule>
The different directives are as follows:
StartServers – The number of servers (processes) to start when Apache is started
Min/MaxSpareServers – Desired number of idle processes
ServerLimit / MaxClients – Sets the Apache process limit
MaxRequestsPerChild – The maximum number of requests a process can handle before it dies. For KeepAlive requests, only the first request is counted towards this limit. This is useful as over time the processes may consume more memory, and this will require a process to restart after X amount of requests.
The default MaxClients value for Apache is 256. As outlined above, for small web servers, this will quickly consume all of the servers memory under medium to heavy load, which will likely lead to other services being killed by the Linux kernel i.e. your database getting shut down. It is important to know how to configure the Prefork MPM as well as how to test the various configurations to find the optimal process settings.