Nginx 504: Operation timed out while reading response — Исправление
Клиент делает запрос (например, генерация сложного PDF отчета, экспорт базы данных или долгий API-вызов), браузер крутит индикатор загрузки 60 секунд и падает с ошибкой 504 Gateway Time-out. В логе: upstream timed out (110: Operation timed out) while reading response header from upstream.
| Директива таймаута | Значение по умолчанию | Смысл параметра |
|---|---|---|
proxy_read_timeout | 60s | Максимальное время ожидания ответа от бэкенда между двумя операциями чтения |
fastcgi_read_timeout | 60s | Лимит времени выполнения FastCGI скрипта для Nginx |
uwsgi_read_timeout | 60s | Лимит ожидания ответа от WSGI-приложений |
- Соединение с бэкендом успешно устанавливается, но бэкенд вычисляет данные дольше 60 секунд.
- Сам процесс бэкенда продолжает работать на сервере, даже когда клиент уже получил ошибку 504.
- Локализуйте тяжелый эндпоинт по логу ошибок
/var/log/nginx/error.log. - Для долгих операций увеличьте таймауты чтения в соответствующем блоке
locationNginx:location /api/v1/export/ { proxy_pass http://backend_upstream; proxy_connect_timeout 60s; proxy_send_timeout 300s; proxy_read_timeout 300s; } - Если используется FastCGI (PHP-FPM):
location ~ \.php$ { include fastcgi_params; fastcgi_pass unix:/run/php/php8.2-fpm.sock; fastcgi_read_timeout 300s; } - Увеличьте лимит выполнения на стороне самого приложения (например,
max_execution_timeвphp.iniили таймаут worker в Gunicorn--timeout 300). - Примените обновленную конфигурацию:
sudo nginx -s reload.
Частые вопросы (FAQ)
Почему увеличение proxy_read_timeout не помогло?
Потому что таймаут мог сработать на уровне самого бэкенда (например, max_execution_time в PHP, statement_timeout в PostgreSQL или timeout в Gunicorn). Все таймауты в цепочке должны быть согласованы.
Что означает proxy_send_timeout?
Это таймаут передачи запроса от Nginx к бэкенду (между двумя операциями записи), а не передачи всего тела запроса целиком.
Продолжает ли бэкенд работать после отдачи клиенту 504 Gateway Timeout?
Да, если в приложении не настроена обработка отмены контекста (client disconnect), бэкенд продолжит выполнять вычисления и нагружать базу данных вхолостую.
Как задать бесконечный таймаут для WebSocket соединений?
Установите proxy_read_timeout 86400s; (сутки) и убедитесь, что передаются заголовки Upgrade и Connection.