502 Bad Gateway: что значит и как починить
Ошибка 502 Bad Gateway означает, что прокси-сервер (nginx, Apache, Cloudflare) не получил валидный ответ от upstream-сервера (PHP-FPM, Node.js, uwsgi, Gunicorn). Это не проблема прикладного кода, а сбой между прокси и backend'ом.
В статье разберём, что конкретно означает 502 в разных stack'ах, 7 частых причин и пошаговые решения для nginx + PHP-FPM, Node.js и Apache, с примерами конфигов.
Что означает 502
По RFC 9110 §15.6.3, 502 указывает, что сервер, действуя как gateway или proxy, получил некорректный ответ от upstream. В отличие от 504 (timeout), 502 — это синтаксический или соединительный провал: upstream упал, вернул мусор или reset соединения.
Архитектура запроса и где возникает 502
Browser → CDN/Cloudflare → nginx → PHP-FPM / Node.js / uwsgi
↑
502 от этого звена, если upstream:
- не отвечает
- вернул невалидный HTTP
- закрыл соединение
- timeout при connect()7 частых причин 502
- PHP-FPM / Node.js упал или не запущен.
- Worker пул исчерпан — все children заняты.
- OOM Killer убил процесс — система исчерпала RAM.
- Upstream timeout при connect().
- Сломанный socket (unix socket удалён или без прав).
- Deploy в процессе — upstream перезапускается.
- Слишком большие заголовки — buffer переполнен.
Диагностика 502
Проверьте внешне через HTTP Header Checker от Enterno.io, затем копайте серверные логи.
# Статус процессов
systemctl status php8.4-fpm
systemctl status nginx
pm2 list # для Node.js
# Логи
tail -100 /var/log/nginx/error.log
tail -100 /var/log/php8.4-fpm.log
# Проверьте OOM Killer
dmesg | grep -i "killed process\|out of memory"
journalctl --since "10 minutes ago" | grep -i oom
# Проверьте socket
ls -la /var/run/php/php8.4-fpm.sock
# Должно быть: srw-rw---- 1 www-data www-dataРешения
1. Перезапустить upstream
systemctl restart php8.4-fpm
systemctl restart nginx
# или PM2
pm2 restart all2. Увеличить worker пул PHP-FPM
# /etc/php/8.4/fpm/pool.d/www.conf
pm = dynamic
pm.max_children = 50
pm.start_servers = 10
pm.min_spare_servers = 5
pm.max_spare_servers = 20
pm.max_requests = 500
# Для высокой нагрузки:
pm = static
pm.max_children = 100
pm.max_requests = 1000
systemctl reload php8.4-fpmПравильный размер пула: max_children = (RAM - 500MB) / avg_worker_MB. Мониторьте через pm.status_path = /fpm-status.
3. Увеличить buffer и timeout в nginx
http {
# Увеличьте если upstream отправляет большие заголовки
fastcgi_buffer_size 128k;
fastcgi_buffers 8 128k;
fastcgi_busy_buffers_size 256k;
# Увеличьте timeout для медленных upstream
fastcgi_connect_timeout 30s;
fastcgi_send_timeout 60s;
fastcgi_read_timeout 60s;
# Для проксирования к Node.js
proxy_buffer_size 128k;
proxy_buffers 8 128k;
proxy_busy_buffers_size 256k;
proxy_connect_timeout 30s;
proxy_read_timeout 60s;
}4. Проверить и починить socket
# Если используете unix socket
listen = /var/run/php/php8.4-fpm.sock
listen.owner = www-data
listen.group = www-data
listen.mode = 0660
# Альтернатива — TCP (меньше проблем с правами):
listen = 127.0.0.1:90005. Защита от OOM
# Увеличьте memory_limit в PHP осторожно
memory_limit = 256M
# swap файл (для VPS с малой RAM)
fallocate -l 2G /swapfile
chmod 600 /swapfile
mkswap /swapfile
swapon /swapfile
echo "/swapfile none swap sw 0 0" >> /etc/fstab
# Приоритет OOM для критичных процессов
systemctl edit php8.4-fpm
# [Service]
# OOMScoreAdjust=-5006. Graceful deploy с zero-downtime
# Blue-green через nginx
upstream backend {
server 127.0.0.1:3000; # blue
server 127.0.0.1:3001 backup; # green
}
# Reload вместо restart
systemctl reload php8.4-fpm # без downtime
pm2 reload all # zero-downtime restart7. Node.js специфика
// Unhandled rejection = процесс упадёт = 502
process.on('unhandledRejection', (reason) => {
logger.error('Unhandled Rejection:', reason);
// Не вылетаем — продолжаем работать
});
process.on('uncaughtException', (err) => {
logger.error('Uncaught Exception:', err);
// Стратегия: логируем и продолжаем (или graceful shutdown)
});
// PM2 для автоматического restart
// pm2 start app.js --max-memory-restart 500M502 от Cloudflare — что делать
Если Cloudflare показывает 502 с ID cf-ray:
- Проверьте, что origin отвечает напрямую (обойдите CF через
curl -H 'Host: example.com' http://ORIGIN_IP). - Проверьте проверку SSL на origin — истёкший = 502 от CF.
- Уточните, что origin не блокирует CF IP ranges (WAF, firewall).
- Проверьте CF Workers — ошибка в коде worker возвращает 502.
Мониторинг и предотвращение
Настройте Enterno.io Monitors с expected_code=200 и регионами ru-msk + eu-de — вы сразу узнаете о 502, даже если он виден только из определённой географии. Подключите Telegram или Slack для мгновенных алертов.
Часто задаваемые вопросы (FAQ)
В: Чем отличается 502 от 504?
О: 502 — upstream вернул мусор или закрыл connection. 504 — upstream не ответил за отведённое время.
В: Почему после deploy возникает 502?
О: Upstream перезапускается. Решение: graceful reload вместо restart + zero-downtime deploy через PM2/systemd.
В: 502 только иногда — что проверять?
О: Worker пул, OOM Killer, timeout на медленных запросах, состояние socket'а.
Заключение
502 — проблема между прокси и backend'ом. Всегда начинайте с проверки статуса upstream процессов, затем логов. Правильно настройте пул worker'ов, buffer'ы, timeout'ы и защиту от OOM. мониторинг сайтов через Enterno.io поймает регрессии мгновенно.
Проверьте ваш сайт прямо сейчас
Проверить →