504 Gateway Timeout: повільні бекенди й 502 vs 503 vs 504
504 Gateway Timeout означає, що проксі дістався вашого бекенда, чекав на відповідь і здався, перш ніж вона прийшла. Нічого не впало і ніщо не відмовило в запиті: щось за проксі повільніше, ніж проксі готовий чекати.
Що повідомляє 504
RFC 9110 визначає 504 для сервера, що діє як шлюз чи проксі й не отримав вчасної відповіді від upstream-сервера, до якого йому потрібно було звернутися. Слово "вчасної" визначає конфігурація, а не специфікація, тож 504 завжди твердження одразу про дві речі: наскільки повільним був бекенд, і на який ліміт було налаштовано проксі.
З цього випливає важливий практичний наслідок. Коли проксі повертає 504, бекенд зазвичай продовжує працювати над запитом. З'єднання з клієнтом зникло, але повільний запит усе ще виконується, звіт усе ще генерується, а ресурси все ще утримуються. Саме тому хвиля 504 часто робить сервер ще гіршим: кожен покинутий запит лишає по собі роботу, і черга росте швидше, ніж спустошується.
504 проти 502 проти 503
| 502 Bad Gateway | 503 Service Unavailable | 504 Gateway Timeout | |
|---|---|---|---|
| Що сталося | Бекенд дав невалідну відповідь чи закрив з'єднання | Сервер навмисно відхилив роботу | Бекенд прийняв роботу й так і не відповів вчасно |
| Стан бекенда | Лежить, падає чи говорить не тим протоколом | Працює, але перевантажений чи на обслуговуванні | Працює й зайнятий, усе ще обробляє |
| Швидкість відповіді | Зазвичай миттєва | Зазвичай миттєва | Повільна, приходить на межі тайм-ауту |
| Типовий рядок логу | connect() failed чи upstream prematurely closed connection | Правило обслуговування, чи жодного здорового upstream | upstream timed out (110: Connection timed out) |
Retry-After | Не типово | Поширено й рекомендовано | Не типово |
| Де шукати спершу | Чи запущений процес бекенда? | Потужність, прапорці обслуговування, перевірки здоров'я | Повільні запити й повільні залежності |
На практиці 502 провалюється швидко, 503 ввічливо відмовляє, а 504 спершу змушує чекати. Присвячений посібник з 502 і огляд 5xx повністю охоплюють два інші коди.
Чому бекенд надто повільний
- Повільні запити до бази даних. Відсутній індекс, запит, що виріс разом із даними, патерн N+1 у циклі чи конкуренція за блокування при паралелізмі. Найпоширеніша окрема причина.
- Повільні виклики сторонніх сервісів. Вихідний API-запит без власного тайм-ауту успадковує найгірший день віддаленого сервісу і передає його вашим відвідувачам.
- Холодні старти. Перший запит після масштабування, старту контейнера чи періоду бездіяльності платить за ініціалізацію, встановлення з'єднань і прогрівання кешу все одразу.
- Справді важка робота на вебзапиті. Генерація звітів, експорти, обробка зображень чи масові імпорти, оброблені синхронно, врешті перевищать будь-який розумний тайм-аут.
- Конкуренція за ресурси. Насичення CPU, тиск на пам'ять і своп роблять кожен запит повільнішим, тож найповільніші перетинають межу першими.
- Занадто жорсткі тайм-аути. Якщо ендпоінту законно потрібно більше часу, ніж дозволяє проксі, баг у конфігурації, а не в коді.
- Мережеві проблеми між переходами. Втрата пакетів чи затримки розв'язання DNS для upstream-адреси додають затримку, яка не з'являється в таймінгах застосунку.
Як діагностувати й виправити 504
- Виміряйте час до помилки. Затримка перед 504 зазвичай збігається з налаштованим тайм-аутом, що показує, який перехід її спричинив:
504 майже рівно на 60 секундах указує на тайм-аут читання проксі за замовчуванням. Той, що на 30 чи 100 секундах, указує на той компонент, що налаштований на це число, часто CDN, а не ваш власний проксі.curl -sS -o /dev/null -w "%{http_code} %{time_total}s\n" https://example.com/slow-page - З'ясуйте, це один ендпоінт чи всі. Одна повільна URL-адреса - проблема застосунку. Усе повільне одразу - насичення ресурсів чи залежність, що провалюється.
- Прочитайте лог помилок проксі. У nginx рядок явний:
Він називає upstream і фазу, що відрізняє повільне з'єднання від повільної відповіді.[error] upstream timed out (110: Connection timed out) while reading response header from upstream, upstream: "http://127.0.0.1:8080/" - Виміряйте час бекенда напряму, без проксі. Якщо той самий запит триває 90 секунд до origin, проксі повідомляє правду, і виправлення належить у застосунок.
- Профілюйте повільний шлях. Перевірте лог повільних запитів, тоді трейси застосунку. Більшість 504 зводяться до одного запиту чи одного вихідного виклику.
- Виправляйте причину, а не тайм-аут. Додайте індекс, закешуйте дорогий результат, чи перенесіть справді довгу роботу у фонове завдання, що відповідає одразу й окремо звітує про прогрес.
- Підвищуйте тайм-аут лише коли робота законно довга, і робіть це послідовно на кожному переході. Ліміт CDN у 30 секунд робить тайм-аут origin у 120 секунд безглуздим.
- Встановлюйте тайм-аути на власних вихідних викликах, щоб повільна залежність провалювалася швидко з чіткою помилкою, а не споживала воркера, поки проксі не здасться.
Час відповіді - раннє попередження
504 - кінцевий стан уповільнення, що накопичувалося якийсь час. Час відповіді дрейфує від пів секунди до двох секунд до десяти, і ніхто цього не помічає, поки запити не почнуть перетинати межу. Запланована HTTP-перевірка записує час відповіді кожної перевірки поряд із кодом статусу, тож тренд видно як графік задовго до першого тайм-ауту, а сповіщення приходить на першому справжньому збої, а не після того, як заповниться черга підтримки. Перевірка з кількох регіонів теж допомагає, бо маршрут, швидкий з одного континенту й повільний з іншого, вказує на мережевий шлях чи конфігурацію edge, а не на вашу базу даних.