Debugging Apache Timeouts: Analyzing Slow AJAX Requests and Server Hangs


6 views

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