The log entries showing child processes exiting after exactly 200-300 seconds indicate a systematic behavior rather than random performance issues. The key observations:
[03-Sep-2013 09:25:23] NOTICE: [pool www] child 23999 exited with code 0 after 321.832329 seconds from start
[03-Sep-2013 09:25:41] NOTICE: [pool www] child 24032 exited with code 0 after 259.247887 seconds from start
The current FPM pool configuration shows several parameters that might contribute to this behavior:
pm = dynamic
pm.max_children = 50
pm.start_servers = 20
pm.min_spare_servers = 5
pm.max_spare_servers = 35
pm.max_requests = 100
The most likely explanations for this pattern include:
- Process reaching
pm.max_requests
limit (though your config shows 100) - PHP script execution timeouts (check
max_execution_time
in php.ini) - Idle process cleanup (especially with
process_idle_timeout
setting) - System-level process killers (OOM killer, systemd watchdogs)
To identify the exact cause, run these diagnostic commands while monitoring the logs:
# Check PHP-FPM process status
sudo systemctl status php-fpm
# Monitor process lifecycle
watch -n 1 'ps aux | grep php-fpm | grep -v grep'
# Check system logs for OOM events
sudo grep -i kill /var/log/syslog
Adjust these parameters in your pool configuration:
; Recommended adjustments
pm.max_requests = 500 ; Increase if processes are recycling too quickly
request_terminate_timeout = 300s ; Explicit timeout setting
request_slowlog_timeout = 10s ; Log slow requests
process_idle_timeout = 10s ; If using ondemand pm
Consider these additional optimizations:
; Enable status page for monitoring
pm.status_path = /status
; Enable slow log for troubleshooting
slowlog = /var/log/php-fpm/slow.log
; Adjust process manager settings
pm.max_spare_servers = 20 ; Reduce if experiencing frequent recycling
pm.process_idle_timeout = 30s ; For dynamic/ondemand PM
For deeper analysis, implement this monitoring script:
#!/bin/bash
while true; do
DATE=$(date +%Y-%m-%d\ %H:%M:%S)
PROCESS_COUNT=$(pgrep -c php-fpm)
MEM_USAGE=$(ps -o rss= -p $(pgrep php-fpm) | awk '{sum+=$1} END {print sum/1024}')
echo "[$DATE] Processes: $PROCESS_COUNT | Memory: ${MEM_USAGE}MB"
sleep 5
done
When examining PHP-FPM logs with entries like:
[03-Sep-2013 09:25:23] NOTICE: [pool www] child 23999 exited with code 0 after 321.832329 seconds from start
The "seconds from start" value represents the total lifetime of a PHP-FPM child process before it terminated gracefully (exit code 0). This indicates process recycling behavior.
The provided configuration shows:
pm = dynamic
pm.max_children = 50
pm.start_servers = 20
pm.min_spare_servers = 5
pm.max_spare_servers = 35
pm.max_requests = 100
Key factors affecting process lifetime:
pm.max_requests
: Process terminates after serving 100 requests- Process manager may recycle idle workers based on spare server settings
Several scenarios can cause this behavior:
// Example of problematic PHP code that might cause long process lifetimes
function heavy_processing() {
// Memory-intensive operation
$large_array = array_fill(0, 1000000, 'data');
// Long-running operation
for ($i = 0; $i < 1000000; $i++) {
// Complex calculations
}
}
Adjust PHP-FPM settings to control process lifetime:
; Recommended adjustments for production
pm.max_requests = 500 ; Balance between stability and performance
pm.process_idle_timeout = 60s ; Kill idle workers after 60 seconds
request_terminate_timeout = 120s ; Maximum execution time
Use these commands to monitor PHP-FPM:
# Show process status
sudo systemctl status php-fpm
# Real-time monitoring
sudo watch -n 1 "ps aux | grep php-fpm"
# Detailed process information
sudo strace -p <php-fpm-pid>
Consider these additional optimizations:
; php.ini adjustments
opcache.enable=1
opcache.memory_consumption=128
opcache.max_accelerated_files=4000
realpath_cache_size=4096K
realpath_cache_ttl=600
For Nginx integration:
location ~ \.php$ {
fastcgi_pass unix:/var/run/php-fpm.sock;
fastcgi_read_timeout 60;
fastcgi_send_timeout 60;
fastcgi_connect_timeout 60;
}