There are a number of MPM modules (Multi-Processing Modules), but by far the most widely used (at least on *nix platforms) are the three main ones: prefork
, worker
, and event
. Essentially, they represent the evolution of the Apache web server, and the different ways that the server has been built to handle HTTP requests within the computing constraints of the time over its long (in software terms) history.
mpm_prefork
is.. well.. it's compatible with everything. It spins off a number of child processes for serving requests, and the child processes only serve one request at a time. Because it's got the server process sitting there, ready for action, and not needing to deal with thread marshaling, it's actually faster than the more modern threaded MPMs when you're only dealing with a single request at a time - but concurrent requests suffer, since they're made to wait in line until a server process is free. Additionally, attempting to scale up in the count of prefork child processes, you'll easily suck down some serious RAM.
It's probably not advisable to use prefork unless you need a module that's not thread safe.
Use if: You need modules that break when threads are used, like mod_php
. Even then, consider using FastCGI and php-fpm
.
Don't use if: Your modules won't break in threading.
mpm_worker
uses threading - which is a big help for concurrency. Worker spins off some child processes, which in turn spin off child threads; similar to prefork, some spare threads are kept ready if possible, to service incoming connections. This approach is much kinder on RAM, since the thread count doesn't have a direct bearing on memory use like the server count does in prefork. It also handles concurrency much more easily, since the connections just need to wait for a free thread (which is usually available) instead of a spare server in prefork.
Use if: You're on Apache 2.2, or 2.4 and you're running primarily SSL.
Don't use if: You really can't go wrong, unless you need prefork for compatibility.
However, note that the treads are attached to connections and not requests - which means that a keep-alive connection always keeps a hold of a thread until it's closed (which can be a long time, depending on your configuration). Which is why we have..
mpm_event
is very similar to worker, structurally; it's just been moved from 'experimental' to 'stable' status in Apache 2.4. The big difference is that it uses a dedicated thread to deal with the kept-alive connections, and hands requests down to child threads only when a request has actually been made (allowing those threads to free back up immediately after the request is completed). This is great for concurrency of clients that aren't necessarily all active at a time, but make occasional requests, and when the clients might have a long keep-alive timeout.
The exception here is with SSL connections; in that case, it behaves identically to worker (gluing a given connection to a given thread until the connection closes).
Use if: You're on Apache 2.4 and like threads, but you don't like having threads waiting for idle connections. Everyone likes threads!
Don't use if: You're not on Apache 2.4, or you need prefork for compatibility.
In today's world of slowloris, AJAX, and browsers that like to multiplex 6 TCP connections (with keep-alive, of course) to your server, concurrency is an important factor in making your server scale and scale well. Apache's history has tied it down in this regard, and while it's really still not up to par with the likes of nginx or lighttpd in terms of resource usage or scale, it's clear that the development team is working toward building a web server that's still relevant in today's high-request-concurrency world.
Best Answer
Recognize that Ubuntu 14.04 uses Apache 2 with PHP running through an mpm_prefork module, of which an editable file is in /etc/apache2/mods-enabled/mpm_prefork.conf. Also, recognize that starting in Apache 2.4, MaxClients is now renamed as MaxRequestWorkers, and so any documentation regarding MaxClients needs to be switched to MaxRequestWorkers.
Stop the Apache web service with the following command, temporarily:
Read the Mem: line and look at the free column. Consider this as the amount of RAM that you can dedicate to Apache, although I usually like to deduct 2GB on a beefier server (as in > 4GB), or 1GB on a lighter server. So, if the free column said I had 13GB free, I would recommend giving Apache 11GB. That's a baseline. If we encounter any database issue in the logs occasionally (as in like 3 times in the logs over a 3 day period) that it needs more memory, then we might consider that we only had 10GB to play with instead of 11GB (in this case). If we encounter in the Apache logs that the server needs more MaxRequestWorkers, then that's a separate issue I'll address below.
Open like 10 browser tabs, connect to some of your longer or slower-loading pages from your website, and refresh like 3-4 times on each tab.
After doing that, rapidly now run the following command:
Run it like 5 times rapidly.
Look at the Average Process Size value and average that value out among the 5 times you ran that.
Now do the following math, and be sure to convert GB to MB as necessary so that all the numbers are in MB values. So, either multiply times 1024 or divide by 1024, depending on which way you need to go.
MaxRequestWorkers = Baseline Free (with buffer space) / Avg Process Size
For example, I had a 14GB server, but when Apache was stopped the server showed it used 1GB RAM in idle. I then provide another 1GB in some extra buffer space for the OS in case it needs it. That means I would have a Baseline Free of 12GB. Now I must convert it from GB to MB, and so I multiply 12 x 1024 and get 12288. The 12288 MB is my Baseline Free value. In my case I saw that the Average Process Size was 21MB. So, I take 12288 / 21 and I get approximately 585. Now, it's common that sysops round down this value, and so I got 580.
Note that you may not see the ServerLimit parameter there. Add it. This parameter defaults to 256 if not present, but needs to be the same value as MaxRequestWorkers or you'll get an error.
Another critical factor in your Apache configuration is the /etc/apache2/apache2.conf file with the Timeout variable and is measured in seconds. This is how long you can send or receive from the server before it times out. You have to also keep in mind a file upload or file download, such as if you have a website where people can upload or download CSV or other large files, for instance. And you need to keep in mind a busy database server and where you might need to provide some time before pages timeout. The smaller you make that Timeout variable, the more available the web server is to receive new connections. Note, however, that setting this value too low may cause havoc with PHP session variables, although not with browser session-based cookies. So, for instance, a value of 300 (5 minutes) might be good for a web server that relies on PHP session variables for web app workflow instead of browser session cookies. A value of 45 might be good for a web server that serves up nothing more than static advertising landing pages, but would be terrible for a server that needs to use PHP session variables a great deal. So, edit the Timeout parameter in this file to the amount you need. This may take some testing with all your web pages to see if the value is too low. It's probably a good idea, however, to not set it higher than 300 unless you're seeing problems in large file uploads or large file downloads.
Now restart your Apache web service. If you did something wrong, Apache will likely tell you about it the moment you start it again, and you can rectify it.
...press CTRL+C to get out of that, should you want.
Look for a complaint about needing MaxRequestWorkers (and recently since you restarted the web server). If you see that even with an optimal MaxRequestWorkers setting, then you're likely needing more firepower for your websites or web applications. Consider these options: