Optimizing Apache and PHP-FPM for High-Traffic WordPress
Managing a high-traffic WordPress site requires moving away from the default Apache configuration. The legacy prefork MPM is resource-intensive because it spawns a process for every single connection. To achieve high concurrency, you must transition to the Multi-Processing Module (MPM) Event combined with PHP-FPM.
Understanding MPM Event
The MPM Event module is designed to handle more concurrent requests by offloading the task of keeping connections open to a dedicated listener thread. This allows the worker threads to process actual requests, significantly reducing the memory footprint compared to prefork.
Configuring the Event Module
Ensure you have disabled mod_php and enabled mod_proxy_fcgi. Edit your mpm_event.conf file (usually located in /etc/apache2/mods-enabled/mpm_event.conf) to tune the parameters based on your server memory:
<IfModule mpm_event_module>
StartServers 3
MinSpareThreads 75
MaxSpareThreads 250
ThreadsPerChild 25
MaxRequestWorkers 2000
MaxConnectionsPerChild 0
</IfModule>
The MaxRequestWorkers setting is critical. It determines the maximum number of concurrent requests. Calculate this by evaluating available RAM and the average memory usage per Apache process.
PHP-FPM Optimization
When using PHP-FPM, you decouple PHP execution from the web server. This allows for independent scaling. The key to performance here is the Process Manager (PM) mode.
Choosing the Right PM Mode
- Static: Fixed number of processes. Best for high-traffic sites with consistent load.
- Dynamic: Processes scale based on demand. Good for sites with fluctuating traffic.
- Ondemand: Processes spawn only when needed. Saves memory but adds overhead for new connections.
For high-traffic WordPress, the Static mode is generally recommended to avoid the overhead of spawning new processes during traffic spikes.
Tuning your Pool Configuration
Modify your pool configuration file (typically /etc/php/8.x/fpm/pool.d/www.conf):
pm = static
pm.max_children = 50
pm.max_requests = 500
To calculate pm.max_children, divide your allocated PHP memory by the average memory usage of a single PHP-FPM worker process. Always leave a buffer for other system processes, such as MySQL or Redis.
System-Level Tuning and Monitoring
Optimization is not a “set and forget” task. Ensure your Linux kernel is tuned for high connection counts by updating /etc/sysctl.conf:
net.core.somaxconn = 1024
net.ipv4.tcp_max_syn_backlog = 2048
net.ipv4.ip_local_port_range = 1024 65535
Finally, always monitor your performance. Tools like htop for process monitoring, apachectl fullstatus for request analysis, and PHP-FPM status pages will provide the data necessary to fine-tune your values over time.
Leave a Reply