Назад | Перейти на главную страницу

Достигнут Apache MaxClients, сервер не отвечает, даже в нерабочее время

У нас есть сервер Apache, который почти ежедневно перестает отвечать на запросы. Проверяя / server-status (mod_status), мы видим, что у нас есть 60 дочерних процессов, которые все находятся в состоянии «W» (отправка ответа).

  1. Если мы бежим service httpd restart все возвращается в норму, и проблема уходит на день или около того.
  2. Если мы вместо перезапуска Apache уничтожим каждый дочерний процесс, проблема останется (это единственный способ получить доступ к / server-status, который будет реагировать, пока все процессы не перейдут в состояние "W").
  3. Мне кажется, что наши сценарии PHP никогда не заканчиваются, когда возникает проблема, что заставило меня подумать, что это проблема тайм-аута MySQL, Solr или PHP / Apache.
  4. Тем не мение...
    • Solr / MySQL отвечает мгновенно.
    • Доступно множество подключений MySQL (мы используем AWS-RDS, максимальное количество разрешенных подключений больше, чем количество процессов Apache).
    • ОЗУ по-прежнему в порядке (каждый процесс составляет 10 м x 60 = 600 МБ ОЗУ, там много свободного).
    • PHP имеет max_exectution_time установлен на «30».
    • Apache TimeOut установлено на «60».
    • Мы не используем постоянные соединения MySQL.
    • Мы делать использовать curl_setopt($conn, CURLOPT_FORBID_REUSE, 0) для запроса Solr (я надеюсь, что это правильно собирает мусор с помощью curl, если соединение разрывается).
  5. По-прежнему кажется, что многие процессы никогда закончить ... Я оставил процесс запущенным, убив все остальные процессы, и этот процесс проработал 2 часа, по-прежнему обслуживая ту же страницу (я мог видеть это в / server-status), которая обычно занимает 50 мсек.
  6. Мы не используем set_time_limit(0) или что-нибудь подобное в нашем коде.
  7. Я полагаю, что опуская set_time_limit означает, что скрипты завершатся после max_execution_time.

У меня была теория, что Apache ListenBacklog установлен слишком высоко, и что всякий раз, когда мы завершаем процессы, мгновенно запускались 60 новых, все пытались ответить клиентам, которые давно ушли. Это объясняет, почему проблема исчезла после перезапуска сервера. Но кажется ListenBacklog не был установлен, и, следовательно, будет использоваться значение по умолчанию «511». Я пытался убить все дочерние процессы несколько раз подряд, чтобы очистить невыполненный журнал, но проблема остается ... все новые запросы к страницам PHP требуют бесконечного ответа (большинство не отвечает).

Конфигурация PHP:

max_execution_time = 30
max_input_time = 60
safe_mode = off

Конфигурация Apache:

KeepAlive off

<IfModule prefork.c>
StartServers       8
MinSpareServers    5
MaxSpareServers   20
ServerLimit      256
MaxClients       60
MaxRequestsPerChild  1000
</IfModule>

У меня кончились идеи ... Будем признательны за любые подсказки!

Я бы рекомендовал следующие шаги по устранению неполадок:

  • strace -p $PID на зависшем процессе, чтобы увидеть, какие системные вызовы, если таковые имеются, он застрял
  • lsof -p $PID в этом процессе, чтобы увидеть, могут ли открытые файловые дескрипторы или сокеты дать вам подсказку
  • tcpdump -vv -A -s1500 port 80 чтобы узнать, какой трафик и где не получается ответить.