CRITICAL FIX: Overhaul PHP-FPM recommendation algorithm for shared hosting safety
- Fix: Memory-based calculator now accounts for MySQL memory usage - Fix: Changed safety buffer from 15% to 50% (much more conservative) - Fix: Hard cap recommendations at 150 max_children per domain on shared hosting - Fix: Added combined capacity validation to prevent OOM scenarios - Fix: Use realistic 20MB per process default instead of 1MB - Fix: Added critical warning when server has <20% RAM headroom - Feature: Step 2b now validates that combined domain recommendations fit in RAM - Feature: Automatically scales down recommendations if they exceed 60% of total RAM - Safety: Previous recommendations of 227 for 8GB server would now be capped at 150 This prevents dangerous situations like: - Domain with 421 requests getting 227 max_children (would need ~28GB) - Combined pools exceeding available RAM - OOM crashes from over-provisioned settings Tested on 8GB server with 2 domains: Now recommends 105 + 31 instead of 227 + 31
This commit is contained in:
@@ -105,30 +105,47 @@ calculate_max_children_memory_based() {
|
||||
local reserved_mb
|
||||
reserved_mb=$(get_field "$reserve_result" 1)
|
||||
|
||||
# Available memory for PHP-FPM
|
||||
local available_mb=$((total_ram_mb - reserved_mb))
|
||||
# Account for MySQL memory (critical on shared hosting!)
|
||||
local mysql_memory_mb=0
|
||||
local mysql_info
|
||||
mysql_info=$(detect_mysql_memory_usage 2>/dev/null)
|
||||
if [ $? -eq 0 ]; then
|
||||
mysql_memory_mb=$(echo "$mysql_info" | cut -d'|' -f3)
|
||||
fi
|
||||
|
||||
# Available memory for PHP-FPM (after system + MySQL reserves)
|
||||
# CRITICAL: This is shared across ALL domains, not per-domain!
|
||||
local available_mb=$((total_ram_mb - reserved_mb - mysql_memory_mb))
|
||||
|
||||
# Safety check: never allow PHP-FPM to use more than 60% of RAM
|
||||
local max_php_fpm=$((total_ram_mb * 60 / 100))
|
||||
if [ "$available_mb" -gt "$max_php_fpm" ]; then
|
||||
available_mb=$max_php_fpm
|
||||
fi
|
||||
|
||||
# Convert average KB to MB
|
||||
local avg_mb=$((avg_kb / 1024))
|
||||
if [ "$avg_mb" -eq 0 ]; then
|
||||
avg_mb=1 # Minimum 1MB to prevent division issues
|
||||
avg_mb=20 # More realistic default (not 1MB)
|
||||
fi
|
||||
|
||||
# Theoretical maximum without safety buffer
|
||||
local theoretical_max=$((available_mb / avg_mb))
|
||||
|
||||
# Apply safety buffer (default 15%, refined later based on traffic patterns)
|
||||
local safety_buffer=15
|
||||
# Apply safety buffer (50% - much more conservative for shared hosting!)
|
||||
# This accounts for peak traffic spikes and other processes
|
||||
local safety_buffer=50
|
||||
local recommended=$((theoretical_max * (100 - safety_buffer) / 100))
|
||||
|
||||
# Sanity checks
|
||||
if [ "$recommended" -lt 2 ]; then
|
||||
echo "2|Minimum safe value (insufficient memory)"
|
||||
elif [ "$recommended" -gt 500 ]; then
|
||||
# Cap at 500 (typical proxy upstream pool size)
|
||||
echo "500|Capped at safe maximum (would be $recommended)"
|
||||
# Hard cap at traffic-realistic limits
|
||||
if [ "$recommended" -lt 5 ]; then
|
||||
echo "5|Minimum safe value (insufficient memory)"
|
||||
elif [ "$recommended" -gt 150 ]; then
|
||||
# CRITICAL: Cap at 150 max per domain on shared hosting
|
||||
# Higher values require dedicated servers
|
||||
echo "150|Capped at safe maximum for shared hosting (would be $recommended)"
|
||||
else
|
||||
local reason="Memory-based: ${avg_mb}MB per process, ${available_mb}MB available, ${safety_buffer}% buffer"
|
||||
local reason="Memory-based: ${avg_mb}MB per process, ${available_mb}MB available (after MySQL: ${mysql_memory_mb}MB), ${safety_buffer}% safety buffer"
|
||||
echo "$recommended|$reason"
|
||||
fi
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user