← 中文资源

简体中文版本

HTTP 408 Request Timeout — 客户端发送过慢

通过提高客户端发送超时、保持连接存活,并防止 slow-loris 式延迟,诊断 408 Request Timeout。

阅读英文原文

症状

本篇调试指南针对“HTTP 408 Request Timeout — 客户端发送过慢”。内容涵盖可观察的症状、可复现的诊断路径、根本原因、具体修复方式,以及如何验证修复并防止回归。

可观察到的症状包括:

  • 服务器对慢速链路上的上传返回 408 Request Timeout
  • 仅移动或高延迟网络下请求失败
  • 日志显示 “client timed out while reading request headers”

诊断

先在隔离环境中复现故障,再按顺序执行以下检查,逐步缩小范围。

步骤 1

curl --limit-rate 1k --max-time 60 -X POST https://api.example.com/upload --data-binary @big.bin -i

限速下出现 408,指向发送超时而非负载问题。

步骤 2

grep -rn "client_header_timeout\|send_timeout\|request_timeout" /etc/nginx/

超时低于真实客户端延迟会产生误报 408;过小并非总是安全。

常见诱因(按出现频率排序):

  • 客户端发送完整请求头或请求体耗时过长
  • 服务端或代理的发送超时小于真实客户端延迟
  • 存在故意缓慢发送数据的 slow-loris 式连接

根因

当客户端未在配置超时内完成请求发送时,服务端以 408 关闭连接。这可防护 slow-loris 攻击,但也会惩罚真正缓慢的客户端。

修复

把客户端发送超时提高到匹配真实延迟,保持合理的 keepalive,大请求体用分块上传,并在边缘做限流,而非仅对慢客户端超时。

注意:过长超时会扩大 slow-loris 攻击窗口;应把宽松超时与连接数及请求速率限制结合。

# nginx: tune client send timeouts
client_header_timeout 30s;
client_body_timeout   30s;
send_timeout          30s;
keepalive_timeout     65s;

# rate limit abusive clients at the edge
limit_req_zone $binary_remote_addr zone=api:10m rate=20r/s;
limit_conn_zone $binary_remote_addr zone=conn:10m;

验证

重试慢速上传并确认完成且无 408;验证故意滥用式的慢连接仍被拒绝。

修复后补充一条回归测试,复现原始症状,防止问题再次出现。

这类故障通常是环境问题而非纯逻辑错误,因此在缺陷记录中应写明完整命令、环境变量与工作目录。请用最小的脚本复现,待最小用例清楚后再扩大范围。为这类故障准备一份简短的排查清单,能显著减少下次排障时间。