Optimizing Apache’s MaxConnections: Solutions for 256 Worker Thread Limit in High-Traffic Environments


2 views

When Apache's worker threads max out at 256 concurrent connections (the default compiled limit), you'll see exactly what you described:

256 requests currently being processed, 0 idle workers

This creates a queuing effect where new connections must wait for available workers, resulting in increased latency or connection timeouts.

Before modifying Apache's configuration, verify your server can handle increased connections:

# Calculate maximum potential memory usage
grep 'MaxClients' /etc/httpd/conf/httpd.conf
ps aux | grep 'httpd' | awk '{print $6/1024 " MB"}' | sort -n

Example output showing memory usage per Apache process:

25.32 MB
26.45 MB
27.11 MB
(...)

Multiply the largest process size by your desired MaxClients value to ensure sufficient RAM.

For modern servers with adequate resources, edit httpd.conf:

# For prefork MPM
<IfModule mpm_prefork_module>
    StartServers         5
    MinSpareServers      5
    MaxSpareServers     10
    MaxClients         400
    MaxRequestsPerChild  4000
</IfModule>

# For worker MPM
<IfModule mpm_worker_module>
    ServerLimit         100
    ThreadLimit         64
    StartServers         2
    MaxClients         3200
    MinSpareThreads     25
    MaxSpareThreads     75 
    ThreadsPerChild     25
</IfModule>

After modifying, gracefully restart Apache:

apachectl -k graceful

Identify slow requests with mod_status enabled:

ExtendedStatus On
<Location /server-status>
    SetHandler server-status
    Order deny,allow
    Deny from all
    Allow from 127.0.0.1
</Location>

Then analyze with:

watch -n 1 "curl -s http://localhost/server-status | grep -E 'W|R|K' | wc -l"

For modern Apache 2.4+ installations, switch to event MPM:

# Stop Apache
service httpd stop

# Switch MPM
yum remove httpd
yum install httpd24u-event

# Configure event MPM
<IfModule mpm_event_module>
    StartServers             3
    MinSpareThreads         75
    MaxSpareThreads        250
    ThreadsPerChild         25
    MaxRequestWorkers      800
    MaxConnectionsPerChild   0
</IfModule>

Validate configuration with ab (Apache Benchmark):

ab -n 1000 -c 100 http://yoursite.com/testpage.html

# Monitor during test
watch -n 1 "netstat -ant | awk '\$6 == \"ESTABLISHED\" {print \$5}' | cut -d: -f1 | sort | uniq -c | sort -n"

Remember to monitor memory usage during peak loads and adjust accordingly.


When your Apache server reaches its default connection limit, you'll see symptoms like:

server-status output:
256 requests currently being processed, 0 idle workers
Load average remains low (e.g., 2.69 on 8 CPUs)
Memory usage under 30%

Option 1: Temporary Connection Increase

Edit your httpd.conf:

# For non-threaded MPM (prefork)
<IfModule mpm_prefork_module>
    ServerLimit      400
    MaxClients       400
    StartServers      10
    MinSpareServers    5
    MaxSpareServers   20
</IfModule>

# For threaded MPM (worker)
<IfModule mpm_worker_module>
    ServerLimit          100
    ThreadLimit          64
    StartServers          4
    MaxClients          4000
    MinSpareThreads      25
    MaxSpareThreads      75
    ThreadsPerChild      25
    MaxRequestsPerChild   0
</IfModule>

Remember to restart Apache after changes:

sudo service httpd graceful  # RHEL/CentOS
sudo systemctl reload apache2  # Debian/Ubuntu

PHP Process Management

Optimize your PHP-FPM pool settings:

[www]
pm = dynamic
pm.max_children = 100
pm.start_servers = 20
pm.min_spare_servers = 10
pm.max_spare_servers = 30
pm.max_requests = 500

Reverse Proxy Setup

Implement Nginx as reverse proxy to handle static content:

server {
    listen 80;
    server_name example.com;

    location / {
        proxy_pass http://localhost:8080;
        proxy_set_header Host $host;
    }

    location ~* \.(jpg|jpeg|png|gif|ico|css|js)$ {
        root /var/www/html;
        expires 30d;
    }
}

KeepAlive Optimization

KeepAlive On
KeepAliveTimeout 2
MaxKeepAliveRequests 100

Module Management

Disable unused modules in httpd.conf:

# Example of modules to potentially disable
LoadModule auth_basic_module modules/mod_auth_basic.so
LoadModule authn_file_module modules/mod_authn_file.so
# Keep enabled:
LoadModule mpm_prefork_module modules/mod_mpm_prefork.so

Create a real-time monitoring script:

#!/bin/bash
while true; do
    echo -n "Connections: "
    netstat -an | grep :80 | wc -l
    echo -n "Apache workers: "
    apachectl fullstatus | grep "requests currently being processed"
    echo "---"
    sleep 5
done

Use mod_status for detailed analysis:

<Location /server-status>
    SetHandler server-status
    Require host localhost
</Location>

Consider these scalable setups:

1. Nginx (frontend) -> Apache (backend)
2. Varnish Cache -> Apache
3. Cloudflare/Load Balancer -> Multiple Apache instances

For source installations:

# Edit include/ap_mmn.h before compiling
#define HARD_SERVER_LIMIT 256  # Change to 1024 or higher
./configure --prefix=/usr/local/apache2 \
            --enable-mods-shared=most \
            --with-mpm=prefork
make && make install