Configuring the Apache MPM on Debian

Now that you know where the files are, let's look at how to tell apache to stay within the memory available to your Debian server.


The apache MPM

Part of the apache web server installation is the "MPM", which stands for "Multi-Processing Method". The MPM determines the mechanism apache uses to handle multiple connections. Now that we have an idea of where apache keeps its configs we'll cover in detail how the main MPMs are configured and how you might optimize their settings for your environment.

The difference

The first thing to know is that there are several MPMs that apache can use, but the main MPMs are "worker" and "prefork".

The worker MPM primarily handles connections by creating new threads within a child process, while the prefork MPM spawns a new process to handle each connection. The worker MPM is considered more efficient, but some modules aren't stable when running under the worker MPM. Installing those modules will replace the worker MPM with the prefork MPM, which is older but more compatible.

Most users won't notice a difference in performance between the MPMs, but it's good to know they're there. If you find your site is having trouble scaling, for example, you might want to switch to the worker MPM even though it isn't recommended by a module you're using. PHP, for instance, will switch apache to the prefork MPM when aptitude installs it, but newer versions of PHP can be compiled with worker MPM support. For a change like that, you'll want to consult your module's documentation to see what it may have to say about apache MPMs.

The important point to take away from this section is that the default aptitude install of apache uses the worker MPM, but several modules (including PHP) will cause aptitude to replace worker with the prefork MPM.

Which am I running?

The easiest way to see which MPM your apache installation is using is to look at which aptitude MPM package is installed. To look at a list of all MPMs available to install, run the command:

aptitude search apache2-mpm-

The output should look something like this:

p   apache2-mpm-event                     - Apache HTTP Server - event driven model            
p   apache2-mpm-itk                       - multiuser MPM for Apache 2.2                       
i A apache2-mpm-prefork                   - Apache HTTP Server - traditional non-threaded model
p   apache2-mpm-worker                    - Apache HTTP Server - high speed threaded model

We won't worry about the unfamiliar MPMs listed there (if you're curious about them, hit the apache documentation site). The important thing in this output is that first column. A "p" indicates an available package, while an "i" indicates a package that is already installed. In the above example, the "i" is next to "apache2-mpm-prefork", so that apache installation is using the prefork MPM.

A less pretty way to go about it (but more definitive) is to run apache2ctl with the "-l" option, like so:

/usr/sbin/apache2ctl -l

The output will be a list of compiled-in modules by the names apache uses for them, like:

Compiled in modules:
  core.c
  mod_log_config.c
  mod_logio.c
  prefork.c
  http_core.c
  mod_so.c

That's not a full list of modules apache loads when it starts, just a list of the modules that are compiled into your base apache installation. That includes the MPM, which in this example is again prefork.

IfModule

Before we dive into the settings for each MPM let's look at how apache knows which settings it should actually read. The "IfModule" directive in apache's config files lets you put a set of instructions into a block that will only be read by apache if the indicated module is loaded.

Note that the module name used by IfModule refers to the module as it's known in the server's code, not its "friendly" name. An IfModule block for the SSL module (mod_ssl) would look like:

<IfModule mod_ssl.c>

Anything in that IfModule block would only be read into the server configuration if mod_ssl is active. That would be the place where SSL-specific directives like "Listen 443" should be found.

Similarly, while you can tell which section applies to which MPM by looking at the comments in the main config file, apache can tell by the IfModule directives. The settings for the prefork MPM can be found in the block that starts:

<IfModule mpm_prefork_module>

And the block containing worker MPM settings starts with:

<IfModule mpm_worker_module>

The main reason we're looking at IfModule is to make sure you can see why different MPM blocks can contain the same directive, but different values. Those settings don't conflict, because apache will only have one MPM loaded when it starts.

It's also useful to note that when you start installing your own modules and configuring them later, IfModule will come in handy. So long as you keep your instructions inside an IfModule block, your web server will be able to start even if that particular module can't be loaded.

Configuring the MPMs

So why all this attention for the MPMs in an apache set-up tutorial? It's not so much because of how the MPMs work as it is that the configuration of your server's MPM can affect how much memory it tries to use. That in turn can affect how responsive the server will be when your site sees a spike in traffic. We're looking at it here instead of in a series on tuning apache performance because these settings don't just affect performance — they can affect the server's stability if the settings aren't suitable for your environment.

While all this detail on MPMs is probably kind of headache-inducing at this point, it's worth it in the long run, honest. At the least, skim through the section for your MPM's settings and revisit them later, after you've put all your virtual hosts in place and taken a couple aspirin.

We can't give a hard and fast "set this option to this" recommendation since server environments vary wildly. What we can do is look at the defaults for each MPM and highlight how changing some can affect your server. The settings are largely similar, so you may notice some duplication between the descriptions.

The default MPM settings are probably best suited to a server environment with 1 GB of memory available. Keep that in mind when you look over the defaults, especially the MaxClients setting.

The prefork MPM

Default:

<IfModule mpm_prefork_module>
    StartServers          5
    MinSpareServers       5
    MaxSpareServers      10
    MaxClients          150
    MaxRequestsPerChild   0
</IfModule>

Again, with the prefork MPM, it's important to keep in mind that a new process (server) is spawned for each connection the server handles.

StartServers

This is the number of child server processes created at startup, ready to handle incoming connections. If you're expecting heavy traffic you might want to increase this number so the server is ready to handle a lot of connections right when it's started.

MinSpareServers

The minimum number of child server processes to keep in reserve.

MaxSpareServers

Maximum number of child server processes that will be held in reserve. Any more than the maximum will be killed.

MaxClients

Sets the maximum simultaneous requests that Apache will handle. Anything over this number will be queued until a process is free to action the request.

MaxClients is not the same as the maximum number of visitors you can have. It is the maximum number of requests that can be fielded at the same time.

Remember the KeepAliveTimeout? This was set low so the connections used by idle web clients can be recycled more quickly to handle new web clients. Each active connection uses memory and counts toward the MaxClients total. If you hit the number of connections in the MaxClients setting, web clients will be stuck waiting for a connection slot to free up.

The trick with MaxClients is that you want the number to be high enough that visitors don't have to wait before connecting to your site, but not so high that apache needs to grab more memory than is available on your server. If you go over the available memory for your server it will start dipping into swap memory, which is slow and ugly and trust me you don't want to do that.

For the prefork MPM, a new process is started when apache handles a new connection. That means MaxClients sets the maximum number of processes apache will create to handle incoming clients. Memory can definitely be a limiting factor here.

The most straightforward way to optimize this setting for the prefork MPM is to look at how much memory each apache process uses when your server sees a decent amount of traffic. Figure out how much memory you want available for apache (taking into account other programs that will use memory, like MySQL), and divide that by the amount of memory you think you want to have available to each of those apache processes. If you don't want to go to all that trouble, then shoot for maybe a MaxClients setting of 40 if you have 256MB on your virtual server. Scale up from there.

MaxRequestsPerChild

Sets how many requests a child process will handle before terminating. The default is zero, which means it will never die.

Why change this if the Max numbers are set as shown above? Well, it can help in managing your Slice memory usage.

If you change the default you give a child a finite number of actions before it will die. This will, in effect, reduce the number of processes in use when the server is not busy, thus freeing memory.

Freeing it for what though? If other software needed memory then it would also need it when the server is under load. It is unlikely you will have anything that requires memory only when the server is quiet.

The worker MPM

Defaults:

<IfModule mpm_worker_module>
    StartServers          2
    MinSpareThreads      25
    MaxSpareThreads      75 
    ThreadLimit          64
    ThreadsPerChild      25
    MaxClients          150
    MaxRequestsPerChild   0
</IfModule>

Each connection in the worker MPM is handled by a thread, and there are several threads per child process (server) started by apache. This approach handles high loads better but can cause problems with modules that aren't built to be "thread safe".

StartServers

This is the number of child server processes created at startup. Each server will run multiple threads to handle incoming connections. If you're expecting heavy traffic you might want to increase this number so the server is ready to handle a lot of connections right when it's started.

MinSpareThreads

The minimum number of threads to keep active in reserve. If the current number of child processes (servers) won't support enough spare threads and the MaxClients won't be exceeded, a new child process will be spawned to supply the spare threads.

MaxSpareThreads

Maximum number of threads that will be held in reserve. Extra child processes may be killed if the MaxSpareThreads number is exceeded, but only if that wouldn't bring the number of spare threads below MinSpareThreads.

ThreadLimit

The absolute limit of threads per child process. Must be equal to or higher than ThreadsPerChild, and requires a restart to change. You'll usually want to make changes to ThreadsPerChild before touching this setting.

ThreadsPerChild

The number of threads (connections) that will be handled by each child process. When a new child process is started, all of its threads are started as well. This basically means that resources (like memory) are allocated to all potential connections for a child process when it is started, and are only freed when that process ends. The default setting of 25 is usually a good compromise between efficiency and the potential for allocating resources for threads that won't be used.

MaxClients

Sets the maximum simultaneous requests that Apache will handle. Anything over this number will be queued until a process is free to action the request.

MaxClients is not the same as the maximum number of visitors you can have. It is the maximum number of requests that can be fielded at the same time.

Remember the KeepAliveTimeout? This was set low so the connections used by idle web clients can be recycled more quickly to handle new web clients. Each active connection uses memory and counts toward the MaxClients total. If you hit the number of connections in the MaxClients setting, web clients will be stuck waiting for a connection slot to free up.

The trick with MaxClients is that you want the number to be high enough that visitors don't have to wait before connecting to your site, but not so high that apache needs to grab more memory than is available on your server. If you go over the available memory for your server it will start dipping into swap memory, which is slow and ugly and trust me you don't want to do that.

For the worker MPM, a new thread is created when apache handles a new connection. This means MaxClients limits the total number of threads apache can create to handle connections.

Optimizing this setting is kind of a juggling act for the worker MPM. You have to take into account the ThreadsPerChild setting, since apache won't create new child processes if that would cause the total number of threads to exceed MaxClients. That lets you cap the memory used by apache, so long as you keep an eye on how much memory an apache child process typically uses, and thus how many of them your virtual server should be able to handle with its available memory. If you're trying to stay under 256 MB on your virtual server you might try starting MaxClients off at 50 and adjust it from there.

MaxRequestsPerChild

Sets how many requests a child process will handle before terminating. The default is zero, which means it will never die.

Why change this if the Max numbers are set as shown above? Well, it can help in managing your Slice memory usage.

If you change the default you give a child a finite number of actions before it will die. This will, in effect, reduce the number of processes in use when the server is not busy, thus freeing memory.

Freeing it for what though? If other software needed memory then it would also need it when the server is under load. It is unlikely you will have anything that requires memory only when the server is quiet.

Summary

If you take nothing else away from this article, let it be that you should tailor your MPM's MaxClients setting so that your web server won't try to allocate more resources than you have available. Better that a visitor wait a moment for a connection than that the server should dip into swap for more memory and bring the entire virtual machine to a crawl.

In the next article we'll look at the main configuration options for apache and what sort of changes can be made to optimize it for your needs.

  • -- Jered

Article Comments:

Mudassir Aftab commented Mon Mar 25 10:44:45 UTC 2013:

My Site has daily 4000 traffic , it reached to 6000 on weekend. Also i hv 3.5 GB RAM and 16 core virtual machine on Citrix. I gave full priority of this machine on Citrix.

please suggest what settings should i use

Apache Memory Usage (MB): 6737.74 Average Proccess Size (MB): 26.951

current MPM settings

<ifmodule> StartServers 16 MinSpareServers 16 MaxSpareServers 32 ServerLimit 1024 MaxClients 1024 MaxRequestsPerChild 50000 </ifmodule>

Want to comment?


(not made public)

(optional)

(use plain text or Markdown syntax)