azurelapp

Understand the Apache event MPM

Apache supports three different Multi-Processing Modules (MPMs) that are responsible for binding to network ports on the machine, accepting requests, and dispatching children to handle the requests.

  • Prefork: Each child process handles one connection at a time. This is the default mode for Apache.

  • Worker: It uses multiple child processes with many threads each.

  • Event: This MPM was designed to allow more requests to be served simultaneously by passing off some processing work to supporting threads and freeing up the main threads to work on new requests.

Bitnami stacks ship all the different MPMs as shared modules so it is possible to configure Apache to enable any of them.

Virtual machines and cloud images are configured for production environments by default. Apache is configured to use the event mode and PHP applications will use the PHP-FPM server for the requests.

PHP-FPM

PHP-FPM (FastCGI Process Manager) is an alternative PHP FastCGI implementation with some additional features useful for heavily-trafficked websites. It has been bundled with PHP since v5.3.3. PHP-FPM has the ability to start workers with different environments and to manage these processes (more information).

The recommended configuration is to configure Apache to serve static files (images, CSS, JavaScript and more) and use PHP_FPM with Apache’s mod_proxy module to handle PHP requests.

MPM event and PHP-FPM for production

The default configuration for Apache and PHP in Linux systems is to use the prefork MPM with an embedded PHP interpreter. This is a very robust configuration but it means that Apache needs to spawn a separate process for every simultaneous request it wants to serve. Because every child process loads a PHP interpreter and associated libraries, this configuration takes a significant amount of memory. In addition to this, a whole process is tied up when waiting for requests when browsers open a persistent connection to the server (which is particularly common with AJAX-heavy web applications).

On high-traffic websites, an alternate MPM (the event MPM) is preferable because it has the ability to serve a large amount of requests while maintaining low memory usage. It does so by using threads to serve requests. It retains some of the stability of a process-based server by keeping multiple processes available, each with many threads so a thread potentially misbehaving would only affect all the other threads in the same process.

Additionally, the event MPM uses a dedicated thread to deal with kept-alive connections, and hands requests down to child threads only when a request has actually been made. That allows those threads to free back up immediately after the request is completed.

Because PHP is not thread-safe on Unix environments (in particular many of its most popular extensions), it is not possible to embed an interpreter in each event MPM process. It needs to live as a separate PHP-FPM process. Apache will serve all static resources (images, CSS, etc.) directly while PHP-FPM serves the PHP-related requests.

In the examples below we provide some benchmarks. We used two different Amazon EC2 instances (micro and small) to run our tests. Both instances had the same WordPress installation and the same memory settings. We used the Siege tool for HTTP load testing and benchmarking. We also used the webpagetest.org tool that allows running speed test from multiple locations using real browsers.

The test below uses the Siege tool to request the WordPress Web page and all its static files. We used 30 concurrent users over 1 minute and obtained the following results:

Small EC2 instance with MPM prefork and mod_php with MPM event and PHP-FPM
Used memory 525MB (Apache) 78MB + 200MB (max) (Apache + PHP-FPM)
Transactions 1606 hits 2480 hits
Availability 89.92 % 91.75 %
Elapsed time 59.08 secs 59.10 secs
Data transferred 12.49 MB 21.30 MB
Response time 0.89 secs 0.69 secs
Transaction rate 27.18 trans/sec 41.96 trans/sec
Throughput 0.21 MB/sec 0.36 MB/sec
Concurrency 24.28 29.11
Successful transactions 1411 2480
Failed transactions 180 223
Longest transaction 5.89 6.17
Shortest transaction 0.11 0.11

The main differences are the following:

  • The used memory is much lower.
  • The amount of data transferred is much higher.
  • The transaction rate is higher and there are less failed transactions.

The next test shows the connection and page serving times of 9 concurrent users using EC2 micro instances with the same WordPress sample site.

Apache MPM prefork with mod_php:

Apache MPM prefork with “mod_php”

Apache MPM event with PHP-FPM:

Apache MPM event with PHP-FPM

The main differences are the following:

  • The load time is much lower in the second case. It is also important that the load time in the first case could be very different for different tests, as it depends on the number of free child processes.
  • The “time to first byte” is much lower in the second case.

The previous test only had 11 static files but in a production PHP application, it is usual to have more and bigger static files. The following example shows a simple static HTML page with 240 small PNG images. We used the Siege tool with 30 concurrent users over 30 seconds.

Small EC2 instance with MPM prefork with MPM event
Used Memory 182MB 66MB
Transactions 2148 hits 3568 hits
Availability 98.90 % 100.00 %
Elapsed time 29.38 secs 29.23 secs
Data transferred 1.10 MB 1.82 MB
Response time 0.25 secs 0.24 secs
Transaction rate 73.11 trans/sec 122.07 trans/sec
Throughput 0.04 MB/sec 0.06 MB/sec
Concurrency 18.32 29.41
Successful transactions 2148 3568
Failed transactions 24 0
Longest transaction 10.55 0.94
Shortest transaction 0.11 0.11

The main differences are the following:

  • The used memory is much lower in the second case.
  • The Transaction rate is much higher in the second case.
  • The Longest transaction is similar to the Shortest transaction.

In conclusion, the Apache event MPM increases the performance of your Apache server, allowing it to serve more requests with less memory. If you want to deploy a PHP application, use PHP-FPM to handle PHP requests. This is highly recommended for running applications on servers with limited memory, such as cloud instances with 512 MB or 1 GB RAM. Bitnami stacks use this configuration by default for virtual machines and cloud images.

Last modification December 21, 2022