Почему Apache отдаёт 503 и причём здесь воркеры
Ошибка 503 Service Unavailable у Apache в реальной эксплуатации чаще связана не с «битой страницей», а с тем, что серверу не хватает свободных обработчиков запросов. Когда все воркеры заняты, новый запрос либо долго ждёт (клиент видит таймаут), либо получает 503 через промежуточный слой (reverse proxy, балансировщик, приложение), а Apache пишет характерные сообщения MPM в error log.
Обычно в цепочке участвуют три вещи:
MaxRequestWorkers— сколько запросов Apache может обслуживать параллельно (вpreforkэто процессы, вworker/eventэто потоки);ServerLimit,ThreadLimit— верхние границы: если они ниже, Apache «обрежет» ваши ожидания даже при увеличенииMaxRequestWorkers;KeepAliveиKeepAliveTimeout— сколько времени воркер удерживает соединение, ожидая следующий запрос.
Ключ к быстрой диагностике — понять, почему воркеры не освобождаются: их реально не хватает, они «залипли» в KeepAlive, долго отдают ответы или «доживают» после graceful restart. Это лучше всего показывает scoreboard.
Симптомы в логах: какие AH errors искать
Начинайте с error log Apache в момент всплеска 503. Самое прямое указание на причину выглядит так:
AH00161: server reached MaxRequestWorkers setting, consider raising the MaxRequestWorkers setting
Если вы уже пытались поднять MaxRequestWorkers, но «ничего не изменилось», проверьте, не режет ли Apache ваше значение ограничителем сверху:
AH00165: ServerLimit of 256 not above MaxRequestWorkers of 400, decreasing MaxRequestWorkers to 256
Снаружи будет тот же 503, а внутри вы фактически работаете на меньшем пуле, чем ожидаете.
Вторичные «намёки», почему воркеры не освобождаются вовремя (и вы упираетесь в лимит), чаще всего такие:
- долгая отдача контента и медленные клиенты (воркеры висят в отправке ответа);
- зависания на приложении (CGI/FastCGI/прокси к бекенду), из-за чего запросы «висят»;
- всплеск keepalive-соединений, которые удерживают воркеры в ожидании;
- частые
graceful restart(деплой/ротация), из-за чего часть воркеров долго «доживает» старые соединения.
Как быстро подтвердить: status, scoreboard и моментальный снимок
Если включён mod_status, это самый быстрый путь: вы видите текущий пул, занятость и главное — строку scoreboard (таблица состояний воркеров). Нас интересуют:
- сколько воркеров доступно по лимитам и сколько занято;
- какие состояния доминируют в
scoreboard; - есть ли признаки «подрезания» лимитов (косвенно через лог AH00165 и т. п.).
Если mod_status недоступен на проде, всё равно можно подтвердить упор в воркеры по связке: error log (AH00161/AH00165) + количество процессов/потоков + число активных соединений. Но именно scoreboard лучше всего отвечает на вопрос «воркеры заняты чем?».

Легенда scoreboard: как читать «забитую» таблицу
В mod_status вы увидите строку со значками — это и есть scoreboard. Набор может слегка отличаться по версиям, но смысл обычно такой:
_— idle (ожидание);R— чтение запроса;W— отправка ответа (часто долгие скачивания или медленный клиент);K— KeepAlive (соединение держится, воркер занят ожиданием);D— DNS lookup (редко, но бывает при проблемах резолвинга);L— логирование;G— graceful finishing (воркер завершает старую работу, часто послеgraceful restart).
Типовая интерпретация «почему нет свободных воркеров»:
- много
K— keepalive удерживает воркеры; первым делом смотрятKeepAliveTimeoutи характер клиентов/фронтенда; - много
W— воркеры долго отдают данные; ищем тяжёлые URL, большие ответы, медленных клиентов, отсутствие/неэффективность кеширования; - много
G— частыеgraceful restartили слишком долго живущие соединения, из-за чего воркеры «доживают» и пул очищается медленно; - много
Rпри маломW— подозрение на аномалии трафика или проблемы чтения от клиента.
MPM: prefork vs event — почему одинаковые настройки ведут себя по-разному
Сообщение «server reached MaxRequestWorkers» одинаковое, но лечится по-разному из-за модели параллелизма.
prefork: процессы и «дорогие» воркеры
prefork обслуживает запросы отдельными процессами. Это просто и совместимо со «старыми» модулями, но каждый процесс обычно дороже по памяти. Если без расчёта поднять MaxRequestWorkers, можно упереться в RAM, затем в swap, а дальше получить лавинообразную деградацию и те же 503 (только уже не от лимита, а от тормозов ОС).
Правило для prefork: сначала оцените реальную память процесса Apache при типичной нагрузке (особенно когда PHP живёт внутри Apache), затем поднимайте лимиты с запасом под ОС, кеши и соседние сервисы.
event: потоки и более эффективный KeepAlive
event (и близкий worker) использует процессы с потоками. Важное отличие: keepalive-соединения обслуживаются эффективнее, воркеры не «залипают» так дорого, как в prefork. Поэтому при большом числе клиентов с KeepAlive event обычно держится лучше.
Но у event тоже есть «жёсткая математика» по лимитам: неверное сочетание ThreadsPerChild, слишком маленький ServerLimit или упор в ThreadLimit приводят к тому, что реальная параллельность ниже ожидаемой.
MaxRequestWorkers и ServerLimit: как менять правильно (и не ухудшить)
Ключевая мысль: MaxRequestWorkers не живёт отдельно. Его нужно согласовать с тем, как Apache формирует пул воркеров в выбранном MPM.
Настройки для prefork
Для prefork критично: ServerLimit должен быть не ниже MaxRequestWorkers, иначе Apache «обрежет» настройку (обычно это видно по AH00165).
ServerLimit≥MaxRequestWorkersMaxRequestWorkersвыбирается по RAM и средней памяти на процесс Apache
Пример фрагмента конфигурации (значения примерные):
<IfModule mpm_prefork_module>
ServerLimit 200
MaxRequestWorkers 200
StartServers 10
MinSpareServers 10
MaxSpareServers 20
</IfModule>
Настройки для event
Для event связь такая: MaxRequestWorkers примерно равен ServerLimit × ThreadsPerChild. Если задать больше — Apache снова «обрежет» (и напишет об этом в лог).
Пример фрагмента:
<IfModule mpm_event_module>
ServerLimit 16
ThreadsPerChild 25
MaxRequestWorkers 400
ThreadLimit 64
</IfModule>
Проверьте два условия:
ThreadsPerChildне должен упираться вThreadLimit;ServerLimitдолжен быть достаточным, чтобы «добрать» нужное число потоков до вашегоMaxRequestWorkers.
Поднимать
MaxRequestWorkersимеет смысл только когда узкое место именно в параллелизме Apache. Если узкое место в RAM/CPU/приложении/БД, вы просто увеличите конкуренцию за ресурсы и ускорите деградацию.
KeepAlive: когда помогает и когда «съедает» MaxRequestWorkers
KeepAlive уменьшает накладные расходы на установку TCP/TLS и ускоряет сайты с множеством мелких ресурсов. Но при неудачных значениях и «плохих» клиентах он начинает удерживать воркеры в ожидании, и вы упрётесь в MaxRequestWorkers значительно раньше.
Типовой сценарий: много K в scoreboard и всплеск 503
Если в scoreboard преобладает K, воркеры заняты ожиданием следующего запроса в рамках keepalive. На HTTP/1.1 это особенно заметно: соединение одно, запросы идут редко, а воркер уже занят.
Что обычно делают в эксплуатации:
- снижают
KeepAliveTimeoutдо разумного (часто 1–5 секунд хватает); - проверяют
MaxKeepAliveRequests, если есть клиенты, которые «выедают» соединения сериями; - если Apache за фронтендом, отдельно оценивают keepalive между фронтендом и Apache: он может держать много долгих соединений «пачками».
Пример стартовой настройки (не догма):
KeepAlive On
KeepAliveTimeout 2
MaxKeepAliveRequests 100
Если вы раздаёте много статики через Apache и видите много W/K, проверьте заголовки кеширования и корректность отдачи. В тему может быть полезна заметка про Cache-Control и ETag для статики.
Graceful restart: как применить изменения без простоя и где подвох
graceful restart хорош тем, что Apache старается не рвать активные соединения: текущие воркеры «доживают» свои запросы, а новые поднимаются параллельно. Подвох в том, что при большом числе долгих запросов или keepalive вы можете на время получить повышенное потребление ресурсов и рост состояния G в scoreboard.
Практические рекомендации:
- не делайте частые
graceful restart«по расписанию», если нет причины; - при деплоях следите за длительностью запросов и keepalive, чтобы «доживание» не копилось;
- если после перезапуска видите всплеск 503 и много
G, уменьшайте частоту перезапусков и разбирайтесь, что их запускает (деплой, ротация, панель, CI).
Практический чек-лист диагностики Apache 503
Проверить error log: есть ли
AH00161; нет ли сообщений о сниженииMaxRequestWorkersиз-заServerLimit/ThreadLimit(например,AH00165).Посмотреть
scoreboard: что доминирует —K,WилиG. Это сразу задаёт направление работ.Уточнить MPM:
preforkилиevent(для них разные расчёты и разные риски по памяти/keepalive).Сверить математику лимитов:
- для
prefork:ServerLimit≥MaxRequestWorkers; - для
event:ServerLimit×ThreadsPerChild≈MaxRequestWorkers, иThreadLimitне должен мешать.
- для
Проверить KeepAlive: если много
K— уменьшатьKeepAliveTimeoutи проверять клиентов/фронтенд.Оценить «длинные» ответы: если много
W— искать тяжёлые URL, большие ответы, медленных клиентов, проблемы приложения/БД/внешних API.Вносить изменения постепенно и применять через
graceful restart, контролируя RAM/CPU и динамику AH-сообщений.

Готовые сценарии: что менять в зависимости от scoreboard
Сценарий A: преобладает K (KeepAlive)
Начните со снижения KeepAliveTimeout. Затем проверьте, нет ли клиентов с аномально большим числом одновременных соединений. Если Apache стоит за фронтендом, отдельно посмотрите keepalive между фронтендом и Apache: иногда именно он удерживает соединения «пачками», съедая доступные воркеры.
Сценарий B: преобладает W (Send Reply)
Если при доминировании W вы упираетесь в MaxRequestWorkers, значит ответы слишком долгие или слишком большие. Типовые действия: найти самые тяжёлые URL, оптимизировать приложение и запросы к БД, включить/проверить кеширование, разгрузить отдачу больших файлов, проверить, нет ли зависаний на внешних вызовах.
Сценарий C: много G после частых перезапусков
Уменьшайте частоту graceful restart, фиксируйте, кто инициирует перезапуски, и планируйте их на окно меньшей нагрузки. Если долгие соединения неизбежны, следите, чтобы «доживание» воркеров не копилось.
Что важно зафиксировать после исправления
Когда 503 ушли, стоит закрепить базовую «точку отсчёта», чтобы в следующий пик быстро понять, что именно закончилось:
- пиковое число занятых воркеров и запас до
MaxRequestWorkers; - распределение состояний
scoreboardв норме и в пик; - время ответа (среднее и 95-й перцентиль) на основных URL;
- частота
graceful restartи причины перезапусков.
Если вы выбираете площадку под проект, где ожидаются пики и важны предсказуемые лимиты по CPU/RAM, удобнее держать Apache и приложение на VDS: проще масштабировать ресурсы и контролировать MPM/лимиты без сюрпризов соседей.
А если Apache работает как фронтенд под много доменов, не забывайте про актуальные TLS-настройки: корректно настроенные SSL-сертификаты снижают риск странных клиентских ретраев и лишних переподключений, которые тоже «съедают» соединения в пике.
С такой базой при следующем всплеске вы быстро увидите по логам и scoreboard, что именно стало узким местом: воркеры, keepalive, «доживание» после рестартов или тормоза приложения.


