408 Request Timeout
Применение
Когда приходит ошибка 408 Request Timeout, клиент начал запрос, но по какой-то причине не передал полезную нагрузку целиком. Это происходит, когда интернет-соединение медленное или было разорвано. Ответ включает заголовок Connection, указывающий, что соединение закрыто.
Получив заголовок Connection: close, клиент повторяет запрос.
Примечание
408 Request Timeout означает, что клиент слишком медленно отправлял запрос серверу. 504 Gateway Timeout означает, что прокси или шлюз не дождался ответа от внутреннего сервера. 408 — это тайм-аут между клиентом и сервером, тогда как 504 — тайм-аут между серверами. 408 — один из немногих кодов 4xx, которые оправдывают автоматический повтор, поскольку причина обычно кратковременна.
Влияние на SEO
Поисковые системы вроде Google не индексируют URL, возвращающий статус 408. Ранее проиндексированные URL, которые возвращают этот код состояния, удаляются из результатов поиска.
Пример
Клиент начинает отправлять серверу PDF-файл размером 10K, но соединение страдает от перебоев связи, и сервер делает вывод, что передача идёт слишком медленно. Сервер отменяет запрос и закрывает соединение. Когда соединение стабилизируется, клиент успешно передаёт файл повторно.
Первоначальный запрос
PUT /docs HTTP/1.1
Host: example.com
Content-Type: application/pdf
Content-Length: 10000
Первоначальный ответ
HTTP/1.1 408 Request Timeout
Connection: Close
Content-Type: text/html
Content-Length: 198
<html>
<head>
<title>Connection Close</title>
</head>
<body>
<p>The transmission was not received quickly
enough. Check connectivity and try again.</p>
</body>
</html>
Следующий запрос
PUT /docs HTTP/1.1
Host: example.com
Content-Type: application/pdf
Content-Length: 10000
<File transfer successful for PDF file>
Итоговый ответ
HTTP/1.1 200 OK
Как исправить
408 Request Timeout означает, что сервер закрыл соединение, поскольку клиент не завершил запрос вовремя.
Проверьте сетевую связность и задержку. Нестабильное или медленное соединение задерживает передачу запроса. Выполните ping и traceroute до сервера, чтобы выявить потерю пакетов или узлы с высокой задержкой. Убедитесь, что соединение стабильно, прежде чем повторять попытку.
Уменьшите размер полезной нагрузки или разбейте крупные загрузки. Отправка большого файла по медленному соединению превышает терпение сервера. Сожмите полезную нагрузку, используйте блочное Transfer-Encoding или разбейте загрузку на меньшие части с помощью API многокомпонентной загрузки.
Увеличьте настройки тайм-аутов на стороне клиента. HTTP-библиотека клиента или браузер применяет собственный тайм-аут. Поднимите значения тайм-аутов соединения и чтения, чтобы учесть более медленные передачи. В curl используйте —connect-timeout и —max-time. В Python requests задайте timeout=(connect, read).
Проверьте конфигурацию тайм-аутов на сервере. Настройте директивы тайм-аутов в зависимости от веб-сервера:
nginx:
client_header_timeout 60s;
client_body_timeout 60s;
keepalive_timeout 75s;
send_timeout 60s;
Apache:
Timeout 60
KeepAliveTimeout 5
RequestReadTimeout header=20-40 body=20
Директива RequestReadTimeout (mod_reqtimeout) управляет тайм-аутами чтения заголовков и тела по отдельности. Увеличьте эти значения, когда клиентам действительно нужно больше времени.
Настройте параметры Keep-Alive. Низкое значение keepalive_timeout закрывает простаивающие соединения до того, как клиент отправит следующий запрос в постоянном соединении. В nginx значение keepalive_timeout по умолчанию составляет 75 секунд. Поднимите его для API, обслуживающих клиентов с неравномерным, всплесковым характером запросов. В Apache увеличьте KeepAliveTimeout (по умолчанию 5 секунд) и убедитесь, что MaxKeepAliveRequests допускает достаточное число запросов на соединение.
Проверьте тайм-ауты обратного прокси и балансировщика нагрузки. Когда перед сервером приложения стоит обратный прокси (nginx, HAProxy, AWS ELB), каждый уровень применяет собственный тайм-аут. Прокси закрывает соединение первым, если его тайм-аут короче, чем у внутреннего сервера. В режиме обратного прокси nginx:
proxy_connect_timeout 60s;
proxy_read_timeout 60s;
proxy_send_timeout 60s;
У AWS ALB тайм-аут простоя по умолчанию составляет 60 секунд и настраивается в атрибутах балансировщика нагрузки.
Повторите запрос. 408 часто носит кратковременный характер. Заново установите соединение и отправьте полный запрос повторно. Для программных клиентов реализуйте логику автоматического повтора с экспоненциальной выдержкой. Заголовок Retry-After, если он присутствует, указывает, сколько ждать перед повторной попыткой.
Изучите журналы ошибок сервера. nginx записывает события тайм-аутов в журнал ошибок. Apache фиксирует нарушения mod_reqtimeout. Проверьте /var/log/nginx/error.log или /var/log/apache2/error.log на записи, соответствующие времени запроса, чтобы определить, истёк ли тайм-аут при чтении заголовков или тела.
Примеры кода
.NET
HttpStatusCode.RequestTimeout
Rust
http::StatusCode::REQUEST_TIMEOUT
Rails
:request_timeout
Go
http.StatusRequestTimeout
Symfony
Response::HTTP_REQUEST_TIMEOUT
Python3.5+
http.HTTPStatus.REQUEST_TIMEOUT
Java
java.net.HttpURLConnection.HTTP_CLIENT_TIMEOUT
Apache HttpComponents Core
org.apache.hc.core5.http.HttpStatus.SC_REQUEST_TIMEOUT
Angular
@angular/common/http/HttpStatusCode.RequestTimeout