408 Request Timeout
用法
收到 408 Request Timeout 错误时,客户端已发起请求,但出于某种原因未能传输完整的载荷。这在互联网连接缓慢或已断开时发生。响应中包含 Connection 头,表明连接已被关闭。
在收到 Connection: close 头后,客户端会再次尝试请求。
注意
408 Request Timeout 意味着客户端向服务器发送请求太慢。504 Gateway Timeout 意味着代理或网关在等待后端服务器响应时超时。408 是客户端到服务器的超时,而 504 是服务器到服务器的超时。408 是少数值得自动重试的 4xx 状态码之一,因为其成因通常是瞬时的。
SEO 影响
像 Google 这样的搜索引擎不会索引返回 408 状态的 URL。此前已被索引、如今返回该状态码的 URL 会从搜索结果中移除。
示例
客户端开始向服务器发送一个 10K 的 PDF 文件,但连接遭遇间歇性的连通性问题,服务器判定传输过慢。服务器取消请求并关闭连接。当连接稳定后,客户端成功重新传输该文件。
初始请求
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)。
核实服务器的超时配置。根据 Web 服务器调整超时指令:
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