ZIM-НИЙ SAAALEЗимние скидки: до −50% на старт и −20% на продление
до 31.01.2026 Подробнее
Выберите продукт

Apache 503 Service Unavailable: уперлись в MaxRequestWorkers, KeepAlive и scoreboard — как найти и исправить

503 в Apache часто означает не «упал сайт», а «закончились воркеры». Разберём, как по AH-ошибкам и scoreboard понять причину, учесть различия prefork и event, настроить MaxRequestWorkers/ServerLimit и KeepAlive и безопасно применить изменения без простоя.
Apache 503 Service Unavailable: уперлись в MaxRequestWorkers, KeepAlive и scoreboard — как найти и исправить

Почему 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 (деплой/ротация), из-за чего часть воркеров долго «доживает» старые соединения.
FastFox VDS
Облачный VDS-сервер в России
Аренда виртуальных серверов с моментальным развертыванием инфраструктуры от 195₽ / мес

Как быстро подтвердить: status, scoreboard и моментальный снимок

Если включён mod_status, это самый быстрый путь: вы видите текущий пул, занятость и главное — строку scoreboard (таблица состояний воркеров). Нас интересуют:

  • сколько воркеров доступно по лимитам и сколько занято;
  • какие состояния доминируют в scoreboard;
  • есть ли признаки «подрезания» лимитов (косвенно через лог AH00165 и т. п.).

Если mod_status недоступен на проде, всё равно можно подтвердить упор в воркеры по связке: error log (AH00161/AH00165) + количество процессов/потоков + число активных соединений. Но именно scoreboard лучше всего отвечает на вопрос «воркеры заняты чем?».

Фрагмент Apache server-status со строкой 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).

  • ServerLimitMaxRequestWorkers
  • MaxRequestWorkers выбирается по 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 для статики.

Виртуальный хостинг FastFox
Виртуальный хостинг для сайтов
Универсальное решение для создания и размещения сайтов любой сложности в Интернете от 95₽ / мес

Graceful restart: как применить изменения без простоя и где подвох

graceful restart хорош тем, что Apache старается не рвать активные соединения: текущие воркеры «доживают» свои запросы, а новые поднимаются параллельно. Подвох в том, что при большом числе долгих запросов или keepalive вы можете на время получить повышенное потребление ресурсов и рост состояния G в scoreboard.

Практические рекомендации:

  • не делайте частые graceful restart «по расписанию», если нет причины;
  • при деплоях следите за длительностью запросов и keepalive, чтобы «доживание» не копилось;
  • если после перезапуска видите всплеск 503 и много G, уменьшайте частоту перезапусков и разбирайтесь, что их запускает (деплой, ротация, панель, CI).

Практический чек-лист диагностики Apache 503

  1. Проверить error log: есть ли AH00161; нет ли сообщений о снижении MaxRequestWorkers из-за ServerLimit/ThreadLimit (например, AH00165).

  2. Посмотреть scoreboard: что доминирует — K, W или G. Это сразу задаёт направление работ.

  3. Уточнить MPM: prefork или event (для них разные расчёты и разные риски по памяти/keepalive).

  4. Сверить математику лимитов:

    • для prefork: ServerLimitMaxRequestWorkers;
    • для event: ServerLimit × ThreadsPerChildMaxRequestWorkers, и ThreadLimit не должен мешать.
  5. Проверить KeepAlive: если много K — уменьшать KeepAliveTimeout и проверять клиентов/фронтенд.

  6. Оценить «длинные» ответы: если много W — искать тяжёлые URL, большие ответы, медленных клиентов, проблемы приложения/БД/внешних API.

  7. Вносить изменения постепенно и применять через graceful restart, контролируя RAM/CPU и динамику AH-сообщений.

Лог Apache с ошибками AH00161 и AH00165 про MaxRequestWorkers и ServerLimit

Готовые сценарии: что менять в зависимости от 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, «доживание» после рестартов или тормоза приложения.

Поделиться статьей

Вам будет интересно

Linux watchdog: soft lockup/hard lockup, rcu stall и hung task — диагностика по dmesg и связь с I/O OpenAI Статья написана AI (GPT 5)

Linux watchdog: soft lockup/hard lockup, rcu stall и hung task — диагностика по dmesg и связь с I/O

Если сервер подтормаживает или «замирает», а в логе ядра появляются soft lockup/hard lockup, rcu stall или hung task — это не всег ...
Kubernetes NodePort и ExternalTrafficPolicy: как сохранить IP клиента и не сломать балансировку OpenAI Статья написана AI (GPT 5)

Kubernetes NodePort и ExternalTrafficPolicy: как сохранить IP клиента и не сломать балансировку

NodePort и LoadBalancer нередко «съедают» реальный IP клиента из‑за SNAT в kube-proxy. Разберём режимы externalTrafficPolicy (Clus ...
Kubernetes: ErrImagePull и 401 Unauthorized — настройка imagePullSecrets для private registry OpenAI Статья написана AI (GPT 5)

Kubernetes: ErrImagePull и 401 Unauthorized — настройка imagePullSecrets для private registry

Если Pod застрял в ErrImagePull/ImagePullBackOff и в Events виден 401 Unauthorized, почти всегда виноваты imagePullSecrets: секрет ...