Optimizing Apache MPM Worker Configuration for High Concurrency (400+ Concurrent Users)


2 views

Modern Apache installations typically come with three Multi-Processing Modules (MPM):

  • prefork: Process-based model (non-threaded)
  • worker: Hybrid process-thread model
  • event: Enhanced version of worker with better keep-alive handling

First, verify which MPM is active in your Apache installation:

httpd -V | grep -i mpm
# Or for newer systems:
apachectl -V | grep -i mpm

To see all loaded modules:

apachectl -M

For a server with 32GB RAM and SSDs, using mpm_event (recommended for Apache 2.4+) or mpm_worker would be optimal. Here's a sample configuration for mpm_event:


    StartServers             3
    MinSpareThreads         75
    MaxSpareThreads        250
    ThreadsPerChild         25
    MaxRequestWorkers      400
    MaxConnectionsPerChild   0
    ServerLimit             16

1. Create or modify the MPM configuration file (typically in /etc/httpd/conf.modules.d/):

# Disable other MPMs
LoadModule mpm_prefork_module modules/mod_mpm_prefork.so
#LoadModule mpm_worker_module modules/mod_mpm_worker.so
LoadModule mpm_event_module modules/mod_mpm_event.so

2. Verify thread safety for your modules:

# Example check for mod_proxy_ajp
apachectl -M | grep proxy_ajp

Use this formula to estimate maximum workers:

MaxRequestWorkers = (Total RAM - (DB + OS + other services)) / Average Apache process size

To measure process size:

ps -ylC httpd --sort:rss | awk '{sum+=$8} END {print sum/NR/1024 "MB"}'

If you encounter "server reached MaxRequestWorkers":

# Temporary solution during traffic spikes
sudo apachectl graceful

For monitoring active connections:

watch -n 1 "echo -n 'Active: '; netstat -an | grep :443 | wc -l"
  • Enable keepalive with conservative timeout (KeepAliveTimeout 2-5)
  • Set MaxKeepAliveRequests to 100-200
  • Configure proper Timeout values (30-60 seconds)
  • Enable mod_deflate for compression
  • Consider using mod_cache for static content

In CentOS 7 with Apache 2.4.6, you'll typically find three Multi-Processing Modules (MPMs):

# Check installed MPMs
httpd -V | grep -i mpm
# Typical output on CentOS 7:
# Server MPM:     prefork
#  -D MPMSHARED_ON -D MPM_PREFORK

The evolution from older versions means we now have:

  • prefork: Process-based, thread-unsafe modules (PHP 5.x compatibility)
  • worker: Hybrid process/thread model (better for static content)
  • event: Enhanced version of worker (best for keep-alive connections)

Modern Apache installations separate MPM configurations into dedicated files:

# Location of MPM configs in CentOS 7
/etc/httpd/conf.modules.d/00-mpm.conf
/etc/httpd/conf.d/php.conf

To modify worker settings, create or edit:

/etc/httpd/conf.d/mpm-worker.conf

For Tomcat AJP connectivity with 400 concurrent users, consider:

<IfModule mpm_worker_module>
    StartServers            4
    ServerLimit            16
    ThreadLimit            64
    ThreadsPerChild        50
    MaxRequestWorkers     800  # (16*50)
    MinSpareThreads       100
    MaxSpareThreads       400
    MaxConnectionsPerChild 10000
</IfModule>

# AJP Connector in Tomcat's server.xml should match:
<Connector port="8009" protocol="AJP/1.3" 
           maxThreads="500" 
           minSpareThreads="50" 
           acceptCount="300"/>

Critical modules for your stack:

# Check thread safety
httpd -M | grep -E 'proxy_ajp|ssl|vhost'
# For PHP (if used):
php -i | grep Thread

Modern versions of these modules are generally thread-safe:

  • mod_proxy_ajp (thread-safe since 2.2.x)
  • mod_ssl (thread-safe with proper mutexes)
  • mod_vhost_alias (thread-safe)

For 32GB RAM server:

# Estimate with:
(Total RAM - (DB + OS + Tomcat)) / Apache_process_size

# Example calculation:
32GB - (12GB MariaDB + 2GB OS + 4GB Tomcat) = 14GB available
14GB / (50MB avg process) ≈ 280 processes
Suggested MaxRequestWorkers: 800 (using threads)

Final optimized configuration:

<IfModule mpm_worker_module>
    StartServers            4
    ServerLimit            20
    ThreadLimit            64
    ThreadsPerChild        40
    MaxRequestWorkers     800
    MinSpareThreads       200
    MaxSpareThreads       400
    MaxConnectionsPerChild 5000
    ListenBacklog        511
    AsyncRequestWorkerFactor 2
</IfModule>

# In /etc/sysconfig/httpd add:
export LANG=C
ulimit -n 65536

Post-deployment checks:

# Real-time monitoring
apachectl fullstatus
watch -n 1 "ps -ylC httpd --sort:rss"

# Log format for concurrency analysis:
LogFormat "%{%s}t|%D|%{X-Forwarded-For}i|%s|%b|%r" concurrency_log
CustomLog logs/concurrency_log concurrency_log