Подробный гайд: Ошибка 502 Bad Gateway на веб-серверах

Полный разбор ошибки 502 Bad Gateway: причины, диагностика и настройка Nginx, Apache, PHP-FPM и Docker. Быстрые решения для стабильной работы сервера.

2026.05.10                  


Подробный гайд: Ошибка 502 Bad Gateway на веб-серверахПодробный гайд: Ошибка 502 Bad Gateway на веб-серверах

1. Что такое 502 Bad Gateway?

HTTP 502 означает, что сервер, выступающий в роли шлюза (Nginx, Apache, Cloudflare, AWS ALB и т.д.), получил от вышестоящего (upstream) сервера:

  • некорректный HTTP-ответ,
  • пустой ответ,
  • ответ, нарушающий протокол,
  • либо не смог установить соединение вовсе.

Важно:

  • 502 ≠ 503 (Service Unavailable) и ≠ 504 (Gateway Timeout).

На практике их часто путают, но причина разная:

  • 502 → upstream ответил, но ответ "битый" или соединение сброшено.
  • 504 → upstream не ответил в отведённый таймаут.
  • 503 → upstream явно отказался обслуживать запрос (maintenance, overload, circuit breaker).

2. Где возникает 502 в типовой архитектуре

Клиент → CDN/Балансировщик → Z-сеть (Nginx/Apache) → Backend (PHP-FPM/Node/Python/Java) → БД/Сервисы
                                  ↑
                           Здесь появляется 502

Ошибка всегда указывает на стык между Z-сетью и upstream. Клиентский код, браузер или БД редко являются прямой причиной.


3. Топ-7 причин появления 502

Причина Типичные симптомы
1 Backend упал или не запущен connection refused, no live upstreams
2 Нехватка ресурсов/лимиты OOM-kill, pm.max_children исчерпан, queue переполнен
3 Сетевые/файрвол-проблемы iptables, ufw, security groups, DNS resolution failure
4 SSL/TLS mismatches Z-сеть ожидает HTTPS, upstream отдаёт HTTP (или наоборот), просроченный сертификат
5 Контейнерная среда (Docker/K8s) CrashLoopBackOff, failed readiness probe, network policy блокирует трафик

4. Пошаговая диагностика

Шаг 1. Проверьте статус upstream-сервиса

# Systemd
systemctl status php8.3-fpm   # или nodejs, gunicorn, tomcat и т.д.
journalctl -u php8.3-fpm --since "1 hour ago"

# Docker
docker ps -a
docker logs <container_id> --tail 100

# Kubernetes
kubectl get pods -l app=your-backend
kubectl describe pod <pod-name>
kubectl logs <pod-name> --tail 100

Ищите:

  • exited, killed, OOMKilled, CrashLoopBackOff, fatal error.

Шаг 2. Проверьте логи

# Nginx
tail -f /var/log/nginx/error.log | grep "502\|upstream\|connect\|reset"

# Apache
tail -f /var/log/apache2/error.log | grep "AH01114\|502"

Типичные записи:

  • upstream prematurely closed connection
  • no live upstreams while connecting to upstream
  • recv() failed (104: Connection reset by peer)

Шаг 3. Проверьте соединяемость вручную

# Если upstream на порту
curl -v http://127.0.0.1:3000/health
telnet 127.0.0.1 3000
ss -tlnp | grep :3000

# Если upstream на Unix-socket
curl -v --unix-socket /var/run/php/php8.3-fpm.sock http://localhost/
ls -la /var/run/php/

Шаг 4. Проверьте ресурсы системы

htop                # CPU/RAM
free -h             # Swap
df -h               # Диск (особенно /var/log, /tmp)
ulimit -a           # Лимиты открытых файлов
dmesg -T | grep -i oom  # OOM-killer

Шаг 5. Проверьте конфигурацию Z-сети

nginx -t && systemctl reload nginx
apachectl configtest && systemctl reload apache2

5. Решения по популярным стекам

Nginx + PHP-FPM

Проблема:

  • fastcgi_pass указывает на порт, а PHP-FPM слушает сокет (или наоборот).

Решение:

# В /etc/nginx/sites-available/your-site
location ~ \.php$ {
    fastcgi_pass unix:/var/run/php/php8.3-fpm.sock;  # или 127.0.0.1:9000
    fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
    include fastcgi_params;
}

PHP-FPM пул: /etc/php/8.3/fpm/pool.d/www.conf

pm = dynamic
pm.max_children = 50
pm.start_servers = 5
pm.min_spare_servers = 2
pm.max_spare_servers = 10
request_terminate_timeout = 60s
php_admin_value[memory_limit] = 256M

После изменений:

systemctl restart php8.3-fpm

Docker / Kubernetes

Проблема Диагностика Решение
CrashLoopBackOff kubectl describe pod Проверьте env vars, volumes, entrypoint
Readiness probe failed kubectl get events Настройте корректный /health endpoint
Network policy blocks kubectl exec -it <pod> -- curl upstream:port Разрешите трафик в NetworkPolicy
Resource limits too low kubectl top pods Увеличьте resources.limits/requests

6. Типовые ошибки конфигурации и как их избежать

Ошибка Последствие Исправление
worker_connections слишком мал no live upstreams под нагрузкой Увеличьте в events { worker_connections 1024; }

7. Мониторинг и профилактика

1. Health checks
Настройте active или passive проверки upstream:
   upstream backend {
       server 127.0.0.1:3000;
       server 127.0.0.1:3001 backup;
       health_check interval=10s fails=3 passes=2;
   }
2. APM & Tracing

Prometheus + Grafana, Datadog, New Relic, OpenTelemetry. Отслеживайте: - upstream_response_time - nginx_upstream_fail - Backend GC, heap, thread pool

3. Graceful reload/restart
  • Nginx: nginx -s reload
  • PHP-FPM: systemctl reload php8.3-fpm
  • Node/Go: используйте SIGUSR2 или zero-downtime deploy (PM2, systemd socket activation)
4. Логирование с корреляцией

Добавляйте X-Request-ID во все слои. Упрощает поиск причины в распределённой системе.


8. Экспресс-чеклист быстрого восстановления

  • [ ] systemctl status <backend> → запущен?
  • [ ] tail /var/log/nginx/error.log → есть upstream prematurely closed?
  • [ ] curl http://127.0.0.1:<port>/health → отвечает 200?
  • [ ] htop / free -h → нет OOM/CPU starvation?
  • [ ] df -h → диск не забит логами?
  • [ ] Конфиг валиден? nginx -t / apachectl configtest
  • [ ] Последний деплой откатить? docker image ls, kubectl rollout undo
  • [ ] Перезапустить Z-сеть + backend: systemctl restart nginx php8.3-fpm

9. Нюансы для CDN/Cloudflare/Облачных балансировщиков

Если 502 отдаёт Cloudflare, AWS ALB, Yandex Cloud LB:

  1. Проверьте, что origin-сервер доступен извне (не заблокирован файрволом)
  2. Убедитесь, что порт и протокол в настройках CDN совпадают с реальным upstream
  3. Проверьте TLS handshake: openssl s_client -connect yourdomain:443 -servername yourdomain
  4. В Cloudflare: включите Browser Integrity Check off временно для диагностики, проверьте Always Online
  5. Для ALB: проверьте Target Group health checks и deregistration delay

Заключение

502 Bad Gateway — это всегда симптом, а не корневая причина.

Алгоритм всегда один:

Логи → Логи upstream → Статус сервиса → Ресурсы → Сеть/Конфиг → Восстановление/Откат

При правильном логировании, мониторинге и грамотных таймаутах 95% инцидентов решаются за 3–5 минут. Если после прохождения гайда ошибка остаётся — проверьте, не является ли проблема на уровне приложения (deadlock, infinite loop, memory leak), который "обрушивает" upstream, заставляя Z-сеть видеть 502.