502 Bad Gateway: що зламалося за проксі і як це знайти
502 Bad Gateway означає, що проксі перед вашим сайтом запитав у бекенда відповідь і отримав щось невалідне, або взагалі нічого. Проксі працює правильно; він повідомляє, що те, що стоїть за ним, лежить, впало чи говорить не тим протоколом.
Хто повертає 502 і чому
RFC 9110 визначає 502 для сервера, що діє як шлюз чи проксі й отримав невалідну відповідь від вхідного сервера, до якого звертався, намагаючись виконати запит. У кожному сучасному стеку є принаймні один такий перехід: nginx чи Apache перед сервером застосунку, балансувальник навантаження перед флотом, CDN перед вашим origin, чи всі три разом.
Саме ця шаруватість - ключ до читання 502. Компонент, що відповів, достатньо здоровий, щоб згенерувати сторінку помилки. Компонент за ним - ні. Тож 502 завжди розділяє ваш стек на робочу половину й зламану половину, а ваше завдання - з'ясувати, де саме межа.
Його сусіди кажуть дещо вужче. 504 Gateway Timeout означає, що бекенд був досяжний, але надто повільний. 500 означає, що сам бекенд запустився і викинув помилку. 502 означає, що бекенд дав погану відповідь чи взагалі жодної. Повне порівняння в огляді 5xx.
Поширені причини
- Процес бекенда не запущено. Впав сервер застосунку, зупинений пул PHP-FPM, контейнер, що завершився чи провалив перевірку здоров'я. Проксі з'єднується з портом, на якому ніхто не слухає.
- Бекенд упав посеред запиту. Вбивство через нестачу пам'яті чи помилка сегментації закриває з'єднання до того, як заголовки відповіді завершилися.
- Неправильна адреса чи порт upstream. Конфігурація, що вказує на старий порт після зміни, чи на хост, що більше не розв'язується.
- Невідповідність протоколу. Проксі говорить звичайним HTTP до порту, що очікує TLS, чи навпаки. Байти непарсовні, тож проксі називає відповідь невалідною.
- Заголовки відповіді завеликі. Завеликий кукі чи незвично довгий заголовок перевищує буфер проксі, і відповідь відхиляють, а не передають далі.
- Невідповідність keep-alive. Проксі повторно використовує неактивне з'єднання, яке бекенд уже закрив, спричиняючи спорадичні 502 за інакше нормального навантаження.
- Перезапуски й деплої. Будь-яке вікно, коли старий процес зупинився, а новий ще не приймає з'єднання.
- Усі бекенди нездорові. Балансувальнику навантаження, у якого немає жодного члена, що проходить перевірку, нікуди надіслати запит.
Читання логу проксі, що зазвичай закінчує розслідування
Код статусу загальний, але рядок логу проксі конкретний. З nginx варто розпізнавати ці повідомлення:
[error] connect() failed (111: Connection refused) while connecting to upstream,
upstream: "http://127.0.0.1:8080/"
[error] upstream prematurely closed connection while reading response header
from upstream
[error] recv() failed (104: Connection reset by peer) while reading response
header from upstream
[error] upstream sent too big header while reading response header from upstream
[error] no live upstreams while connecting to upstream
Кожне вказує на щось своє:
connect() failed (111: Connection refused). На цій адресі й порту ніхто не слухає. Бекенд зупинено, прив'язано до іншого інтерфейсу, чи він на іншому порту, ніж каже конфігурація.upstream prematurely closed connection. Бекенд прийняв запит, а тоді впав чи завис, не завершивши відповідь. Шукайте збої, вбивства через нестачу пам'яті чи тайм-аут воркера всередині застосунку, а не в nginx.connection reset by peer. Схоже, але з'єднання було активно скинуто. Часто файрвол посередині, чи бекенд, що закрив пулове з'єднання, яке проксі й досі вважав відкритим.upstream sent too big header. Проблема з розміром буфера в проксі, а не вада бекенда. Відповідь валідна, але більша, ніж проксі налаштовано тримати.no live upstreams. Перевірки здоров'я позначили кожен бекенд як недоступний.
Як це виправити
- Перевірте бекенд напряму, оминаючи проксі. З хоста проксі запитайте саму адресу upstream:
200 тут при 502 на публічній URL-адресі означає, що вада в конфігурації проксі чи в зв'язку між ними. Відмова з'єднання означає, що бекенд справді лежить.curl -sS -o /dev/null -w "%{http_code}\n" http://127.0.0.1:8080/ - Перевірте, що бекенд запущений і слухає на адресі, яку очікує проксі. Прив'язка до
127.0.0.1, коли проксі набирає адресу контейнера, - часта причина. - Прочитайте лог помилок проксі й зіставте повідомлення зі списком вище, перш ніж змінювати будь-яку конфігурацію.
- Тоді прочитайте лог бекенда. Збій, вбивство через нестачу пам'яті чи тайм-аут воркера тієї самої секунди підтверджує випадок "prematurely closed". Тиша вказує назад на зв'язність.
- Перевірте адресу upstream, порт і схему в конфігурації проксі, особливо після міграції чи пересборки контейнера.
- Підвищте буфери заголовків проксі, якщо лог каже, що заголовок був завеликий, і окремо з'ясуйте, чому заголовок виріс.
- Зробіть деплої з перекриттям. Запустіть новий процес, дочекайтеся, поки він пройде перевірку здоров'я, тоді спорожніть і зупиніть старий. Rolling-оновлення, прив'язані до здоров'я, повністю усувають вікно перезапуску, що спричиняє 502 на момент деплою.
Як упіймати 502, що триває двадцять секунд
502 на момент деплою чи в циклі падінь короткі. Бекенд перезапускається, видає помилку двадцять секунд і відновлюється, тож на момент, коли хтось перевіряє, сайт у порядку, і дивитися вже нема на що. Запланована HTTP-перевірка, що працює безперервно, записує ці вікна з мітками часу, що перетворює "щось було дивне сьогодні вранці на коротко" на патерн, який можна зіставити з деплоями й перезапусками. 502 також може прийти від краю CDN, а не вашого origin, тож перевірка з кількох регіонів відрізняє глобальний збій бекенда від проблеми edge, що зачіпає частину вашого трафіку, а це саме те, для чого існує розподілений моніторинг доступності.