Ошибки 502 Bad Gateway и 504 Gateway Time-out — самые распространенные и болезненные проблемы на нагруженных веб-сайтах под управлением связки Nginx и PHP-FPM (WordPress, 1C-Битрикс, OpenCart, Laravel). В часы пикового наплыва посетителей, проведения рекламных кампаний или ночных синхронизаций с 1C/CRM сайт внезапно перестает открываться, отдавая пользователям и поисковым роботам белые экраны с системными кодами сбоя.
Для бизнеса каждая минута простоя — это прямая потеря заказов, слитый рекламный бюджет и падение позиций в поисковой выдаче. Однако многие администраторы совершают грубую ошибку: начинают хаотично перезагружать сервер или наугад накручивать параметры в конфигурационных файлах, лишь усугубляя проблему.
В этом руководстве мы разберем проблему на уровне сетевых сокетов и очередей ядра Linux. Вы получите четкий инженерный алгоритм: от локализации первопричины по логам до формул точного расчета пулов памяти и эталонных конфигураций.
1. В чем разница между 502 Bad Gateway и 504 Gateway Time-out
Чтобы быстро устранить аварию, необходимо понимать физику происходящего на уровне протокола FastCGI:
- HTTP 502 Bad Gateway (Недопустимый шлюз): Nginx попытался передать HTTP-запрос в апстрим через UNIX-сокет (
/run/php/php8.3-fpm.sock) или TCP-порт (127.0.0.1:9000), но соединение было сброшено (Connection reset by peer), сокет отсутствовал (No such file or directory), процесс PHP-FPM был принудительно убит ядром Linux (OOM Killer) или размер HTTP-заголовков ответа превысил выделенный буфер Nginx (too big header). - HTTP 504 Gateway Time-out (Время ожидания шлюза истекло): Соединение с PHP-FPM успешно установилось, рабочий процесс принял PHP-скрипт на исполнение, но за отведенное директивой
fastcgi_read_timeoutвремя (по умолчанию 60 секунд) PHP-FPM так и не передал HTTP-ответ. Это классический симптом долгих SQL-запросов, внешних API-запросов без таймаута (cURL) или тяжелой генерации отчетов.
| Характеристика | 502 Bad Gateway | 504 Gateway Time-out |
|---|---|---|
| Состояние PHP-FPM | Остановлен, упал, перегружен, убит по OOM | Работает, но заблокирован / завис на вычислениях |
| Время до отдачи ошибки | Мгновенно (0–50 мс) | Ровно через значение fastcgi_read_timeout (60с+) |
| Типичная причина | Сбой сокета, нехватка RAM, переполнение очереди | Медленный SQL-запрос, зависший cURL, долгий экспорт |
| Основной лог для проверки | /var/log/nginx/error.log, dmesg |
php-fpm-slow.log, mysql-slow.log |
2. Карта логов: точная расшифровка сообщений Nginx и PHP-FPM
Никогда не гадайте о причинах сбоя. В 100% случаев точный диагноз содержится в системных журналах. Откройте терминал сервера и выполните просмотр последних записей:
# 1. Просмотр ошибок Nginx в реальном времени
sudo tail -f -n 50 /var/log/nginx/error.log
# 2. Просмотр системного журнала службы PHP-FPM
sudo tail -f -n 50 /var/log/php8.3-fpm.log
# или через journalctl:
sudo journalctl -u php8.3-fpm -n 50 -f
# 3. Проверка срабатывания OOM Killer в ядре Linux
sudo dmesg -T | grep -i -E "oom|killed process"
Ниже представлена расшифровка наиболее частых записей из /var/log/nginx/error.log:
1. connect() to unix:/run/php/php8.3-fpm.sock failed (111: Connection refused)
Причина: Демон PHP-FPM выключен, упал или сокет не слушается. Решение: sudo systemctl restart php8.3-fpm и проверка статуса.
2. connect() to unix:/run/php/php8.3-fpm.sock failed (2: No such file or directory)
Причина: В конфиге Nginx указан неверный путь к сокету (например, версия php8.1-fpm.sock вместо установленной php8.3-fpm.sock).
3. connect() to unix:/run/php/php8.3-fpm.sock failed (13: Permission denied)
Причина: У пользователя nginx или www-data нет прав на чтение/запись UNIX-сокета. Необходимо проверить директивы listen.owner и listen.group в www.conf.
4. recv() failed (104: Connection reset by peer) while reading response header from upstream
Причина: Рабочий процесс PHP-FPM аварийно завершился прямо во время выполнения скрипта (Segfault, Fatal Error, превышение memory_limit или OOM Killer).
5. upstream sent too big header while reading response header from upstream
Причина: PHP отдал слишком большой объем HTTP-заголовков или множество больших Cookie (часто бывает в 1С-Битрикс и WooCommerce). Буфер FastCGI Nginx переполнился.
6. upstream timed out (110: Connection timed out) while reading response header from upstream
Причина: Истекло время ожидания ответа. PHP-FPM не завершил обработку за время fastcgi_read_timeout.
3. Причина №1: Нехватка воркеров PHP-FPM и расчет pm.max_children
Самая частая причина массовых ошибок 502 на посещаемых сайтах — банальная нехватка рабочих процессов PHP-FPM. Когда все воркеры заняты, новые входящие запросы встают в очередь (listen.backlog). Если очередь заполняется, сокет перестает принимать соединения, и Nginx отдает клиенту 502 Bad Gateway.
В логе /var/log/php8.3-fpm.log это выглядит следующим образом:
[WARNING] [pool www] server reached pm.max_children setting (5), consider raising it
По умолчанию в дистрибутивах Ubuntu/Debian параметр pm.max_children выставлен всего в 5 процессов. Этого достаточно лишь для разработки, но при 20-30 одновременных посетителях сайт моментально падает.
pm.max_children = (Общий объем RAM - RAM под ОС - RAM под MySQL/Redis) / Средний размер процесса PHPПример расчета для сервера 4 GB RAM:
1. Под ОС Linux резервируем 512 MB.
2. Под СУБД MySQL/MariaDB резервируем 1024 MB.
3. Доступно для PHP-FPM:
4096 - 512 - 1024 = 2560 MB.4. Средний размер одного PHP-воркера (WordPress / Bitrix): 50–70 MB.
5.
pm.max_children = 2560 MB / 60 MB ≈ 42. Воспользуйтесь нашим готовым конфигуратором PHP-FPM для 4 GB RAM.Чтобы точно узнать среднее потребление памяти одним PHP-процессом на вашем сервере, выполните команду:
# Средний размер одного процесса php-fpm в мегабайтах (MB)
ps --no-headers -o rss -C php-fpm8.3 | awk '{sum+=$1; count++} END {if (count>0) printf "%.2f MB\n", sum/count/1024; else print "0 MB"}'
Выбор режима менеджера процессов (Process Manager):
pm = dynamic(Рекомендуется для большинства сайтов): Воркеры создаются и уничтожаются динамически в зависимости от нагрузки в диапазоне междуpm.min_spare_serversиpm.max_children.pm = ondemand(Идеально для серверов с десятками сайтов): Процессы поднимаются только при поступлении запроса и завершаются при простое (pm.process_idle_timeout), экономя RAM.pm = static(Для Highload и выделенных серверов): Фиксированное число воркеров постоянно висит в памяти, исключая накладные расходы процессора на спавн процессов.
4. Причина №2: Зависания скриптов и цепочка таймаутов (504)
Ошибка 504 Gateway Time-out возникает, когда одно из звеньев в цепочке веб-сервера обрывает ожидание раньше, чем скрипт успевает завершиться. В веб-стеке существует строгая иерархия таймаутов, которые должны быть согласованы между собой:
Nginx (fastcgi_read_timeout) >= PHP-FPM (request_terminate_timeout) >= PHP (max_execution_time)
| Параметр | Где настраивается | Значение по умолчанию | Рекомендуемое для Production |
|---|---|---|---|
max_execution_time |
/etc/php/8.3/fpm/php.ini |
30s | 60s |
request_terminate_timeout |
/etc/php/8.3/fpm/pool.d/www.conf |
0 (выключен) | 120s |
fastcgi_read_timeout |
/etc/nginx/nginx.conf (или vhost) |
60s | 120s - 180s |
fastcgi_send_timeout |
/etc/nginx/nginx.conf |
60s | 120s |
Как найти зависший PHP-скрипт через PHP-FPM Slowlog:
Включите профилирование медленных запросов в файле /etc/php/8.3/fpm/pool.d/www.conf:
; Путь к журналу медленных скриптов
slowlog = /var/log/php-fpm-slow.log
; Фиксировать в логе скрипты, выполняющиеся дольше 5 секунд
request_slowlog_timeout = 5s
; Глубина стек-трейса вызовов
request_slowlog_trace_depth = 20
После перезагрузки PHP-FPM (systemctl reload php8.3-fpm) в файле /var/log/php-fpm-slow.log будут появляться точные файлы, функции и номера строк кода, на которых зависает выполнение (например, медленный запрос к БД через mysqli_query() или вызов внешнего API через curl_exec()).
5. Надежные VDS-серверы под нагруженные PHP-проекты
Для стабильной работы динамических PHP-приложений критически важны два фактора: высокая тактовая частота процессора (CPU Single-Core Frequency) для быстрой генерации страниц и сверхбыстрые NVMe накопители с задержками I/O менее 0.05 мс. Ниже представлены проверенные облачные платформы, оптимизированные для стека Nginx + PHP + MySQL:
Рекомендуемые VDS-провайдеры
Отказоустойчивые сервера с быстрыми NVMe и каналом до 1 Гбит/с
Премиальная KVM-виртуализация на скоростных процессорах Intel Xeon / AMD EPYC, серверные NVMe SSD диски, 3 ТБ бесплатного трафика на 1 Гбит/с порту и дата-центры Tier III в РФ.
Высокочастотные процессоры High-Freq (до 5.0 GHz), идеальные для быстрой компиляции PHP и работы 1С-Битрикс/WordPress, автоматические снимки дисков и поминутная тарификация.
Легкое развертывание LEMP-стека и баз данных в 1 клик через встроенную панель управления, круглосуточная квалифицированная поддержка 24/7 и стабильный аптайм 99.98%.
6. Причина №3: Размер буферов FastCGI (Upstream sent too big header)
Еще одна неочевидная причина ошибки 502 Bad Gateway на сайтах со сложной авторизацией, корзинами покупок или фреймворками (Bitrix, Symfony, Laravel) — превышение лимитов буферизации заголовков FastCGI.
По умолчанию в Nginx размер буфера под заголовки ответа составляет всего 4k или 8k (размер одной страницы памяти). Если приложение передает длинные сессионные Cookie, JWT-токены или служебные заголовки отладки, Nginx не может прочитать заголовок целиком и мгновенно возвращает клиенту ошибку 502 со следующим логом:
[error] 14210#14210: *8451 upstream sent too big header while reading response header from upstream, client: 198.51.100.4, server: example.com, request: "GET /personal/orders/ HTTP/2.0", upstream: "fastcgi://unix:/run/php/php8.3-fpm.sock:"
Как исправить:
Добавьте в секцию location ~ .php$ или блок http {} файла /etc/nginx/nginx.conf увеличенные буферы:
location ~ .php$ {
try_files $uri =404;
fastcgi_split_path_info ^(.+.php)(/.+)$;
fastcgi_pass unix:/run/php/php8.3-fpm.sock;
fastcgi_index index.php;
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
# Исправление ошибки "upstream sent too big header" и ускорение I/O:
fastcgi_buffer_size 128k;
fastcgi_buffers 256 16k;
fastcgi_busy_buffers_size 256k;
fastcgi_temp_file_write_size 256k;
# Таймауты ожидания ответа
fastcgi_connect_timeout 60s;
fastcgi_send_timeout 120s;
fastcgi_read_timeout 120s;
}
7. Причина №4: Сокеты, права www-data и лимиты ядра Linux
Способ взаимодействия между Nginx и PHP-FPM определяет общую пропускную способность сервера. Доступно два варианта:
- UNIX Domain Socket (
unix:/run/php/php8.3-fpm.sock): Работает через оперативную память ядра без оверхеда сетевого стека TCP/IP. Обеспечивает на 15–25% меньшую задержку (latency) и экономит ресурсы CPU. Оптимален, когда Nginx и PHP-FPM работают на одном сервере. - TCP/IP Socket (
fastcgi_pass 127.0.0.1:9000;): Использует локальный сетевой стек. Необходим при разделении Nginx и PHP-FPM по разным серверам или контейнерам Docker.
Частая ошибка прав доступа на UNIX-сокет:
Если после перезагрузки сервера в логе появляется (13: Permission denied), проверьте конфигурацию /etc/php/8.3/fpm/pool.d/www.conf. Параметры владельца сокета должны соответствовать пользователю Nginx:
; Пользователь и группа для прослушивания сокета
listen = /run/php/php8.3-fpm.sock
listen.owner = www-data
listen.group = www-data
listen.mode = 0660
Тюнинг лимитов ядра Linux (Kernel somaxconn & backlog):
При тысячах одновременных подключений очередь сокета ядра может переполняться. Увеличьте системные лимиты в /etc/sysctl.conf:
# Добавьте в конец файла /etc/sysctl.conf:
net.core.somaxconn = 65535
net.ipv4.tcp_max_syn_backlog = 65535
fs.file-max = 2097152
# Примените настройки без перезагрузки:
sudo sysctl -p
И синхронизируйте очередь в www.conf: установите listen.backlog = 65535.
8. Причина №5: OOM Killer и утечки оперативной памяти
Если в логе Nginx вы видите recv() failed (104: Connection reset by peer), а сервис PHP-FPM периодически самопроизвольно перезапускается — с вероятностью 90% сервер столкнулся с нехваткой RAM, и защитный механизм ядра Linux Out of Memory (OOM) Killer принудительно убил процесс PHP.
Проверьте системный журнал ядра командой:
sudo dmesg -T | grep -i -E "oom|killed process"
Если вывод содержит строки вида Out of memory: Kill process 18452 (php-fpm8.3) score 428 or sacrifice child, предпримите следующие шаги:
- Подключите Swap-файл: Если на сервере 1–2 GB RAM, временная нехватка памяти моментально вызывает падение. Создайте swap размером 2–4 GB на быстром NVMe диске.
- Ограничьте memory_limit в php.ini: Не выставляйте
memory_limit = -1или2048Mбез острой необходимости. Для WordPress/OpenCart достаточно256M, для 1С-Битрикс —512M. - Включите перезапуск воркеров от утечек памяти: В
www.confзадайтеpm.max_requests = 1000. После обработки 1000 HTTP-запросов процесс PHP-FPM мягко завершится и освободит накопленную память, исключая постепенную деградацию сервера. - Включите OPcache: Кэширование байткода PHP в памяти снижает нагрузку на CPU на 70% и ускоряет отклик сайта в 3–5 раз (смотрите наш гайд Оптимизация PHP OPcache).
9. Готовые эталонные конфигурации Nginx и PHP-FPM
Ниже собраны готовые к использованию в продакшене шаблоны конфигураций, протестированные под высокой нагрузкой.
1. Оптимальный пул PHP-FPM (/etc/php/8.3/fpm/pool.d/www.conf для сервера 4 GB RAM):
[www]
user = www-data
group = www-data
listen = /run/php/php8.3-fpm.sock
listen.owner = www-data
listen.group = www-data
listen.mode = 0660
listen.backlog = 65535
; Динамический менеджер воркеров
pm = dynamic
pm.max_children = 40
pm.start_servers = 10
pm.min_spare_servers = 5
pm.max_spare_servers = 15
pm.max_requests = 1000
; Защита от зависаний
request_terminate_timeout = 120s
; Логирование медленных скриптов
slowlog = /var/log/php-fpm-slow.log
request_slowlog_timeout = 5s
request_slowlog_trace_depth = 20
; Системные лимиты
rlimit_files = 65535
catch_workers_output = yes
2. Оптимальный блок FastCGI в Nginx (/etc/nginx/conf.d/php.conf):
# Глобальные параметры буферизации FastCGI
fastcgi_buffer_size 128k;
fastcgi_buffers 256 16k;
fastcgi_busy_buffers_size 256k;
fastcgi_temp_file_write_size 256k;
# Таймауты шлюза
fastcgi_connect_timeout 60s;
fastcgi_send_timeout 120s;
fastcgi_read_timeout 120s;
# Обработка сбоев бэкенда (автоматический переход на кэш при 502/504)
fastcgi_next_upstream error timeout invalid_header http_500 http_503;
fastcgi_next_upstream_tries 3;
fastcgi_next_upstream_timeout 10s;
10. Сводная матрица поиска и быстрого устранения неисправностей
| Код ошибки и симптом | Локализация в логах | Первопричина сбоя | Действие инженера |
|---|---|---|---|
| 502 Bad Gateway | 111: Connection refused |
Служба PHP-FPM остановлена или упала | systemctl restart php8.3-fpm, проверка синтаксиса |
| 502 Bad Gateway | 13: Permission denied |
Nginx не имеет прав на сокет | Установить listen.owner = www-data в www.conf |
| 502 Bad Gateway | server reached max_children |
Все воркеры заняты, очередь переполнена | Увеличить pm.max_children по формуле памяти |
| 502 Bad Gateway | too big header |
Заголовки ответа не влезли в буфер | Задать fastcgi_buffer_size 128k; в Nginx |
| 502 Bad Gateway | 104: Connection reset by peer |
Воркер убит по OOM Killer / Fatal Error | Проверить dmesg, добавить swap, снизить memory_limit |
| 504 Gateway Time-out | 110: Connection timed out |
Скрипт завис на SQL-запросе или cURL | Включить slowlog, оптимизировать индексы БД, поднять timeout |
11. Резюме и чек-лист стабильности
Ошибки 502 и 504 — это не приговор, а четкий индикатор того, что инфраструктура сайта требует балансировки ресурсов и синхронизации параметров стека. Регулярно проводите аудит логов и придерживайтесь проверенного чек-листа:
✅ Чек-лист отказоустойчивости LEMP-стека:
- Параметр
pm.max_childrenрассчитан строго по доступной физической RAM. - Задано значение
pm.max_requests = 1000для защиты от утечек памяти. - Увеличены буферы FastCGI (
fastcgi_buffer_size 128k). - Согласована цепочка таймаутов (Nginx >= PHP-FPM >= PHP).
- Включен журнал медленных запросов
slowlog(от 5 секунд). - Настроен Swap-раздел на случай кратковременных всплесков трафика.
- Включен и настроен OPcache (
opcache.memory_consumption = 256). - Настроена ротация логов (Logrotate для Nginx и PHP), чтобы диск не переполнился.
⚠️ Типичные антипаттерны:
- Увеличение max_children без оглядки на RAM: Если задать 200 воркеров на сервере с 2 GB памяти, при первом наплыве трафика OOM Killer положит весь сервер.
- Завышение таймаутов до 600 секунд: Это маскирует тормозящие SQL-запросы, воркеры остаются заблокированными на 10 минут, и пул мгновенно исчерпывается.
- Использование pm = static на слабых VPS: Пустая трата оперативной памяти при отсутствии реального трафика.
Нужен надежный сервер без сбоев и просадок производительности?
Разверните оптимизированный VDS с аппаратной KVM-изоляцией, процессорами до 5.0 GHz и скоростными NVMe дисками на Selectel.
Развернуть высоконагруженный VDS на Selectel →