400错误因请求头超长,需实测长度后调优large_client_header_buffers:单字段≤size、总头≤单buffer容量;优先分离静态域名去Cookie,再精简Token与前端存储策略。

遇到 400 Bad Request 错误,且日志提示 “client sent too large header” 或 “request header or cookie too large”,大概率是请求头总长超出了 Nginx 的缓冲能力。调优 large_client_header_buffers 不能靠猜,必须基于真实请求头长度分析,再做精准扩容。
确认实际请求头长度
先拿到真实数据,避免过度配置:
- 用浏览器开发者工具的 Network 面板,找到报错的请求,展开 Request Headers,复制全部内容(含换行和冒号空格),粘贴到文本编辑器中统计字符数(注意:URL 编码如
%20算 3 字符,原始空格只算 1 个) - 用 curl 模拟典型长头场景:
curl -I -H "Cookie: $(printf 'a=%s; ' {1..2000})" https://yoursite.com/app.js,逐步增加数量,观察首次返回 400 的临界点 - 查 Nginx error_log,配合
log_format加入$request_length变量,可直接记录每次请求头+行的总字节数(该值包含请求行、所有 headers 和结尾的\r\n\r\n)
理解缓冲区的实际约束条件
large_client_header_buffers 不是简单加总可用内存,它有硬性结构限制:
- 语法为
large_client_header_buffers number size,例如4 16k表示最多分配 4 个缓冲区,每个最大 16KB - 关键规则:**单个请求头字段(如一个 Cookie、一个 Authorization)不能超过
size值**;整个请求头(含请求行 + 所有 headers)必须能放进number个缓冲区中的某一个里(Nginx 不拼接多个 buffer 存一个 header) - 初始缓冲由
client_header_buffer_size提供(默认 1k),若请求头 ≤ 这个值,不触发大缓冲;若略超,但 ≤size,则启用一个大缓冲区即可;若总长 >size,哪怕number很大,也会失败
按需设置参数并验证
根据实测长度,选择最小够用的组合:
- 若实测最长请求头约 10KB,建议设为
large_client_header_buffers 4 16k(单 buffer ≥ 10KB,数量留余量防并发长头) - 同步调整
client_header_buffer_size至4k或8k,减少小请求频繁切换缓冲区的开销 - 把配置放在
server块内,或更精细地放在静态资源location ~* \.(js|css|png|gif|ico)$中,避免影响 API 接口等其他路径 - 修改后务必执行
nginx -t校验,再nginx -s reload生效;用之前复现的 curl 命令再次测试是否不再报 400
比调参更有效的长期解法
单纯扩大缓冲区只是兜底,治本要从源头控制请求头体积:
- 静态资源走独立域名(如
static.example.com),彻底剥离 Cookie,这是最高效的方式 - 后端生成短 Token(如 32 位随机 ID),服务端查表映射完整上下文,替代携带大量用户信息的长 Cookie 或 JWT
- 前端把非必要上下文(AB 测试标识、埋点 session ID)存入
localStorage,仅在需要时通过 API 主动上报,不随每次请求自动发送 - 在 Nginx 入口层用
proxy_set_header清理冗余 header,例如去掉X-Debug-*、User-Agent(静态资源通常不需要)

















