Understanding Apache Multi-Processing Modules (MPM)

<div> <h2>Introduction</h2> Apache HTTP Server is designed as a powerful and flexible web server that operates across multiple platforms and environments. Different platforms and environments often require different features, or may implement identical features more efficiently in various ways. Apache httpd adapts to these diverse environments through a modular architecture. This design enables system administrators to select server features at compile-time or runtime by choosing which modules are loaded into the server. Apache HTTP Server 2.0 extended this modular design to encompass the most fundamental web server functionalities. It provides selectable Multi-Processing Modules (MPMs) that bind to network ports, accept requests, and schedule child processes to handle those requests. This server-level modular design provides two significant advantages: <ul> <li>Apache httpd supports various platforms more gracefully and efficiently. Specifically, the Windows version now performs better because <code>mpm_winnt</code> utilizes native network features instead of the POSIX layer used in Apache httpd 1.3. It can also extend to other platforms using dedicated MPMs.</li> <li>Apache httpd can better accommodate sites with specific requirements. For instance, sites requiring higher scalability can choose threaded MPMs like <code>worker</code> or <code>event</code>; sites requiring reliability or compatibility with legacy software can use <code>prefork</code>.</li> </ul> From the user's perspective, an MPM behaves similarly to other Apache httpd modules. The primary distinction is that at any given time, there must be one and only one MPM loaded on the server. Available MPMs are listed on the module index page. <h2>Default MPMs</h2> The following table lists the default MPMs for different systems. If you do not select one during compilation, this will be the MPM you use. <table> <tbody> <tr> <td>Netware</td> <td><code>mpm_netware</code></td> </tr> <tr> <td>OS/2</td> <td><code>mpmt_os2</code></td> </tr> <tr> <td>Unix</td> <td><code>prefork</code>, <code>worker</code>, or <code>event</code> depending on platform capabilities</td> </tr> <tr> <td>Windows</td> <td><code>mpm_winnt</code></td> </tr> </tbody> </table> <h2>Building MPMs as Static Modules</h2> On all platforms, MPMs can be built as static modules. When building, you select one MPM and link it into the server. If you need to change the MPM, you must rebuild it. To use a specific MPM, execute the <code>configure</code> script with the <code>--with-mpm=<em>NAME</em></code> parameter, where <em>NAME</em> is the desired MPM name. After compilation, you can use <code>./httpd -l</code> to verify the selected MPM. This command lists all modules compiled into the server binary, including the MPM. <h2>Building MPMs as Dynamic Modules</h2> On Unix or similar platforms, MPMs can be built as dynamic modules that load at runtime, similar to other dynamic modules. Building MPMs as dynamic modules allows you to change the MPM by modifying the <code>LoadModule</code> directive without rebuilding the server. To enable this feature when executing the <code>configure</code> script, use the <code>--enable-mpms-shared</code> option. When <em>all</em> is specified as the parameter, all MPM modules supported by the platform will be installed. Alternatively, you can provide a specific list of modules in the parameter. The default MPM can be automatically selected or specified using the <code>--with-mpm</code> option during the <code>configure</code> script execution. It will then appear in the generated server configuration file. Editing the <code>LoadModule</code> directive allows you to select a different MPM. For default yum installations, prefork mode is used: <div> <pre> <code> # Configuration file location /etc/httpd/conf.modules.d # Edit the MPM configuration file vim 00-mpm.conf # Enable prefork MPM LoadModule mpm_prefork_module modules/mod_mpm_prefork.so </code> </pre> </div> For source compilation, include the <code>--enable-mpms-shared</code> parameter: <div> <pre> <code> # Navigate to source directory cd /usr/local/src/httpd-2.4.23 # Configure with shared MPM support ./configure --prefix=/usr/local/httpd-2.4.18 --enable-so --enable-modules="all" --enable-mpms-shared # Build and install make && make install </code> </pre> </div> After installation, configure the MPM module: <div> <pre> <code> # Navigate to extra configuration directory cd /usr/local/httpd/conf/extra # Edit the MPM configuration vim httpd-mpm.conf # Add the MPM module directive LoadModule mpm_prefork_module modules/mod_mpm_prefork.so </code> </pre> </div> <h2>Prefork MPM Configuration</h2> <pre> <code> &lt;IfModule mpm_prefork_module&gt; ServerLimit 256 # Maximum client connections limit (MaxClient) # Default maximum is 256 threads # To increase this value, ServerLimit must be set # Maximum allowed value is 20000 # Must be placed before other directives StartServers 5 # Initial number of child processes created at startup MinSpareServers 5 # Minimum number of idle child processes # If fewer exist, Apache creates new processes # Rate: maximum one per second # Avoid setting this too high MaxSpareServers 10 # Maximum number of idle child processes # Excess processes will be terminated # Avoid setting this too high # If set lower than MinSpareServers, Apache auto-adjusts to MinSpareServers+1 MaxClients 256 # Maximum number of simultaneous client connections # Represents concurrent threads per process # Requests exceeding this limit queue up # Must increase ServerLimit when increasing MaxClients MaxRequestsPerChild 0 # Maximum requests each child process serves before termination # 0 means unlimited (process never expires) # Non-zero values help: # 1. Prevent memory leaks from exhausting memory # 2. Limit process lifespan to reduce active processes during low load &lt;/IfModule&gt; </code> </pre> <h3>Prefork Mode Explanation</h3> Prefork controls the process creation strategy: after initially establishing <code>StartServers</code> child processes, it creates one new process to meet <code>MinSpareServers</code> requirements, waits one second, creates two more, waits another second, then creates four, and continues exponentially up to 32 processes per second until the minimum spare threshold is satisfied. This approach eliminates the need to spawn new processes when requests arrive, reducing system overhead and improving performance. <code>MaxSpareServers</code> defines the maximum number of idle processes. When idle processes exceed this value, Apache automatically terminates excess processes. Avoid setting this value too high. If set below <code>MinSpareServers</code>, Apache automatically adjusts it to <code>MinSpareServers + 1</code>. For high-traffic sites, consider increasing both <code>MinSpareServers</code> and <code>MaxSpareServers</code>. <code>MaxRequestsPerChild</code> defines the maximum requests each child process handles before self-termination. Zero means unlimited, meaning processes never expire. While zero allows each process to handle more requests, non-zero values provide benefits: preventing unexpected memory leaks from consuming all memory, and giving processes a finite lifespan to reduce active process count when server load decreases. The <code>MaxRequestWorkers</code> directive limits concurrent requests. Connections exceeding <code>MaxRequestWorkers</code> queue based on the <code>ListenBacklog</code> directive. In Apache versions before 2.3.13, this directive was called <code>MaxClients</code>. <code>MaxRequestWorkers</code> is the most critical performance parameter, defining the maximum concurrent requests Apache can handle. Its default value of 150 is often insufficient. When the request count reaches this limit (verify with <code>ps -ef | grep http | wc -l</code>), subsequent requests queue until existing requests complete. This explains why system resources appear abundant yet HTTP response is slow. While a larger value theoretically handles more requests, Apache's default ceiling prevents exceeding 256 without recompilation. <h2>Worker MPM Configuration</h2> <pre> <code> # worker MPM directives: # StartServers: initial number of server processes # MinSpareThreads: minimum number of spare worker threads # MaxSpareThreads: maximum number of spare worker threads # ThreadsPerChild: constant number of worker threads per server process # MaxRequestWorkers: maximum number of worker threads # MaxConnectionsPerChild: maximum connections per server process before termination &lt;IfModule mpm_worker_module&gt; StartServers 3 # Number of child processes spawned at server startup MinSpareThreads 75 # Minimum total idle threads across all processes # Default is 75 # When total idle threads fall below this, new child processes spawn additional threads MaxSpareThreads 250 # Maximum total idle threads across all processes # Default is 250 # When total idle threads exceed this, excess threads are terminated # Apache enforces: MaxSpareThreads >= MinSpareThreads + ThreadsPerChild ThreadsPerChild 25 # Fixed number of persistent worker threads per child process # Default is 25 # Threads are created at startup and not replenished MaxRequestWorkers 400 # Maximum number of active worker threads across all processes MaxConnectionsPerChild 0 # Maximum connections each child process serves before termination # 0 means unlimited (process never expires) # Non-zero values prevent memory leaks and enable process cleanup during low load # Note: For KeepAlive connections, only the first request counts # This effectively changes the per-child-process connection limit behavior &lt;/IfModule&gt; </code> </pre> <h3>Worker Mode Explanation</h3> Worker generates <code>StartServers</code> child processes, each containing a fixed number of threads specified by <code>ThreadsPerChild</code>. Threads independently handle requests. Similarly, <code>MinSpareThreads</code> and <code>MaxSpareThreads</code> define the minimum and maximum idle thread counts to avoid creating threads at request time. <code>MaxRequestWorkers</code> sets the maximum concurrent client connections. If existing child processes cannot handle the load, the control process spawns additional child processes. For example: <code>5 StartServers × 25 ThreadsPerChild = 125 MaxRequestWorkers</code>. The default maximum values for <code>MinSpareThreads</code> and <code>MaxSpareThreads</code> are 75 and 250 respectively. These parameters have minimal impact on Apache performance and can be adjusted based on actual requirements. <code>ThreadsPerChild</code> is the most performance-critical directive in worker MPM. Its default maximum is 64, which may be insufficient under heavy load. Use the <code>ThreadLimit</code> directive to increase this, with a maximum default of 20000. The total concurrent request capacity in worker mode is determined by the product of child processes (<code>StartServers</code>) and threads per process (<code>ThreadsPerChild</code>). This product should be greater than or equal to <code>MaxRequestWorkers</code>. Under heavy load, if existing child processes are insufficient, the control process spawns new ones. The default maximum child process count is 16. To increase this, explicitly declare <code>ServerLimit</code> (maximum 20000). Note: If <code>ServerLimit</code> is explicitly declared, the product of <code>ServerLimit</code> and <code>ThreadsPerChild</code> must be greater than or equal to <code>MaxRequestWorkers</code>, and <code>MaxRequestWorkers</code> must be a multiple of <code>ThreadsPerChild</code>. Apache will automatically adjust to appropriate values if these constraints are violated. <h2>Event MPM</h2> <pre> <code> &lt;IfModule mpm_event_module&gt; StartServers 3 # Initial number of server processes at startup MinSpareThreads 75 # Minimum number of spare worker threads to maintain MaxSpareThreads 250 # Maximum number of spare worker threads to maintain ThreadsPerChild 25 # Fixed number of worker threads in each server process MaxRequestWorkers 400 # Maximum number of worker threads MaxConnectionsPerChild 0 # Maximum connections per server process before termination &lt;/IfModule&gt; </code> </pre> <h3>Event Mode Explanation</h3> The two stable MPM configurations above have limitations under very high-traffic server applications. Although HTTP KeepAlive reduces TCP connections and network load, KeepAlive requires binding to service processes or threads, which can exhaust all threads on a busy server. Event MPM solves this problem with a new model that separates service processes from connections. When server processing speed is fast with very high click rates, available thread count becomes the critical resource limitation. At this point, Event MPM is most effective. A busy server operating in worker MPM mode can handle tens of thousands of requests per second (such as during peak hours on major news services), and Event MPM can handle even higher loads. <strong>Important note: Event MPM cannot operate with secure HTTP (HTTPS) access.</strong> </div>

Tags: apache apache-http-server MPM multi-processing-module prefork

Posted on Fri, 30 Oct 2026 16:43:04 +0000 by lettie