When dealing with Apache timeouts affecting ~0.1% of requests (primarily AJAX calls), we need to examine multiple layers:
# Sample Apache log format including microseconds
LogFormat "%h %l %u %t \"%r\" %>s %b %D" custom
CustomLog ${APACHE_LOG_DIR}/timeout_debug.log custom
The mod_reqtimeout findings suggest network issues during body transmission. Consider TCP stack tuning:
# /etc/sysctl.conf adjustments
net.ipv4.tcp_slow_start_after_idle = 0
net.ipv4.tcp_tw_reuse = 1
net.core.somaxconn = 4096
Your prefork settings appear reasonable, but let's optimize for timeout scenarios:
<IfModule mpm_prefork_module>
# Add these to existing config
Timeout 30
AcceptFilter http none # Disables kernel-level connection filtering
EnableSendfile Off # Helps with NFS/slow storage
</IfModule>
Create a dedicated PHP timeout log:
# In php.ini
[PHP]
request_terminate_timeout = 25s
slowlog = /var/log/php_slow.log
request_slowlog_timeout = 5s
The hourly spikes suggest either:
- External monitoring checks
- Filesystem maintenance tasks
- DNS cache expiration
Debug with:
# Capture system state during spikes
while true; do
date;
netstat -tnp;
iostat -x 1 3;
sleep 55;
done > /var/log/spike_monitor.log
Implement client-side timeout detection:
// JavaScript AJAX wrapper with timeout tracking
function trackedAjax(url, data) {
const start = performance.now();
return $.ajax({
url: url,
data: data,
timeout: 10000
}).always(function() {
const duration = performance.now() - start;
if(duration > 2000) {
navigator.sendBeacon('/timeout-logger',
JSON.stringify({url, duration}));
}
});
}
For persistent cases, use systemtap for kernel-level analysis:
# Apache connection stall detector
probe process("apache2").function("ap_process_http_connection") {
if (gettimeofday_ms() - @entry(gettimeofday_ms()) > 5000) {
printf("Slow connection from %s\n",
user_string($conn->remote_ip));
}
}
When dealing with intermittent Apache timeouts (0.1% of total requests at 50s timeout threshold), we observe distinct characteristics:
// Sample request timing distribution
const timeoutStats = {
totalRequests: "100k-200k/day",
timeoutRate: "0.1%",
timeoutThreshold: 50, // seconds
normalResponse: "<1s",
gapPattern: "Clear separation between timeouts and normal requests"
};
Key Apache prefork settings that need examination:
# Recommended diagnostic additions to httpd.conf
ExtendedStatus On
LogLevel debug
CustomLog logs/timeout_debug.log "%h %l %u %t \"%r\" %>s %b %D %X"
The %D
records request duration in microseconds while %X
shows connection status (X=aborted).
Implement packet capture for problematic requests:
# tcpdump filter for AJAX requests timing out
sudo tcpdump -i eth0 -w timeouts.pcap \
'tcp port 80 and (((ip[2:2] - ((ip[0]&0xf)<<2)) - ((tcp[12]&0xf0)>>2)) != 0)' \
-G 600 -W 24
For the specific AJAX endpoints timing out:
// Debug wrapper for AJAX handlers
function debug_wrapper() {
$start = microtime(true);
register_shutdown_function(function() use ($start) {
$duration = (microtime(true) - $start) * 1000;
if ($duration > 5000) { // Log slow requests
error_log(sprintf(
"SLOW AJAX: %.2fms %s %s",
$duration,
$_SERVER['REQUEST_URI'],
json_encode(get_included_files())
));
}
});
}
Enhanced monitoring script for correlation analysis:
#!/bin/bash
while true; do
echo "$(date +%s) $(ps -eo pcpu,pmem,cmd --sort=-pcpu | head -n 5)" \
>> resource_monitor.log
ss -t4 state established -p | grep httpd | awk '{print $4}' \
| sort | uniq -c >> connection_counts.log
sleep 5
done
The mod_reqtimeout findings suggest network-level issues:
# Network quality test script
ping -c 100 example.com | grep "time=" | awk '{print $7}' | cut -d= -f2 \
| stats.py --histogram --percentiles 95,99
For the hourly performance spikes:
# System call tracing during spikes
strace -f -p $(pgrep -f 'httpd|apache2') -c -o strace.out \
-e trace=file,network,ipc
Test configuration with worker MPM:
ServerLimit 16
StartServers 2
MaxClients 150
MinSpareThreads 25
MaxSpareThreads 75
ThreadsPerChild 25
MaxRequestsPerChild 0
MySQL connection verification snippet:
// PHP connection tester
$db = new PDO($dsn, $user, $pass, [
PDO::ATTR_TIMEOUT => 3,
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION
]);
$db->query("SELECT 1")->fetch(); // Verify connection