
网站明明没有宕机,大多数访客也能正常打开,偏偏某个用户一访问就看到“400 Request Header Or Cookie Too Large”。更让人困惑的是,换一个浏览器或者打开无痕窗口,页面又恢复正常。
这种故障通常不是上传文件太大,也不一定是后端程序崩溃,而是浏览器发送给服务器的 Cookie 或其他请求头超过了接入层允许的大小。临时扩大 Nginx 缓冲区可以恢复访问,但如果 Cookie 还在持续累积,错误过一段时间还会回来。
本文从快速判断、日志定位、配置调整和根因治理四个层面,完整说明这类 400 错误应该怎么处理。
一、这个400错误到底表示什么
HTTP 请求由请求行、请求头和可选的请求体组成。Cookie、Authorization、Referer、User-Agent 等信息都位于请求头中。
Nginx 会先使用 client_header_buffer_size 读取普通请求头;当请求行或某个请求头字段放不下时,再使用 large_client_header_buffers 提供的大缓冲区。如果请求行仍然无法容纳,Nginx 会返回 414;如果某个请求头字段仍然过大,则会拒绝请求。Nginx 源码内部使用 494 状态处理“请求头过大”,对外错误页通常表现为 400 Request Header Or Cookie Too Large。
这里有两个容易误判的地方:
client_max_body_size限制的是请求体,主要影响上传文件和较大的 POST 请求,修改它不能解决 Cookie 过大。large_client_header_buffers 4 16k不代表单个 Cookie 字段可以使用 64KB。一个请求行或一个请求头字段必须完整放进单个缓冲区,所以这个示例下单个字段的上限仍受 16KB 缓冲区大小约束。
二、先用无痕窗口做一次快速判断
遇到该错误时,先不要急着修改服务器配置。按下面的顺序测试,通常几分钟就能缩小范围。
1. 使用无痕窗口访问
如果普通窗口报错,无痕窗口可以正常访问,优先怀疑该域名下积累了过多 Cookie。无痕窗口没有沿用原会话中的 Cookie,因此请求头会明显变小。
2. 清除当前站点Cookie
只清除故障域名的 Cookie,然后重新登录。如果错误立即消失,说明问题已经基本确认。不过,这只是恢复访问,并没有解释 Cookie 为什么会变大。
3. 比较故障用户和正常用户
如果只有少数长期登录用户遇到问题,常见原因包括:
- 登录系统重复写入会话 Cookie;
- OAuth、OIDC 或单点登录流程不断累积状态值;
- JWT 中放入过多权限、用户资料或业务字段;
- 同名 Cookie 因 Domain、Path 设置不同而同时发送;
- 已废弃的 Cookie 没有按原来的 Domain 和 Path 正确删除。
如果所有用户同时报错,则还要检查最近是否上线了新的鉴权头、代理规则,或者 CDN、负载均衡器和 WAF 的限制发生了变化。
三、确认错误是在哪一层产生的
真实网站往往不是浏览器直接连接 Nginx,中间可能还有 CDN、WAF、负载均衡器或 Kubernetes Ingress。任何一层的请求头限制更小,都可能提前拒绝请求。
先观察 Nginx 是否收到故障请求:
sudo tail -f /var/log/nginx/error.log |
使用 systemd 管理 Nginx 时,也可以查看服务日志:
sudo journalctl -u nginx --since "30 minutes ago" |
重点留意包含以下含义的记录:
client sent too long header lineclient sent too large request
如果浏览器已经报错,但 Nginx 的访问日志和错误日志里完全没有对应请求,说明请求可能在 CDN、WAF 或负载均衡器处就被拦截了。此时只修改源站 Nginx 不会生效,需要继续检查最外层入口的请求头限制。
四、找出究竟是哪一个请求头过大
在 Chrome 或 Edge 中按 F12 打开开发者工具,切换到 Network,刷新故障页面,再打开对应请求的 Headers 面板。重点查看 Request Headers 中的 Cookie 和 Authorization。
排查时建议记录三项信息:
- 整个请求头的大致大小;
Cookie字段中出现了哪些 Cookie 名称;- 是否存在同名 Cookie、异常长的 JWT,或者成组重复出现的登录状态字段。
不要只使用 document.cookie 判断 Cookie 大小。带有 HttpOnly 属性的 Cookie 不会暴露给页面 JavaScript,但浏览器仍会把它们发送给服务器。开发者工具中的实际请求头更接近服务器收到的内容。
还可以先发送一个不带历史 Cookie 的干净请求进行对照:
curl -I https://example.com/ |
如果干净请求正常,而浏览器原会话持续报错,Cookie 膨胀的可能性很高。需要复现完整请求时,可以在开发者工具里复制为 cURL,但注意删除或打码会话令牌后再保存和分享命令。
五、合理调整Nginx请求头缓冲区
确认请求确实到达 Nginx,且业务当前需要较大的 Cookie 或鉴权头后,可以适度调高缓冲区。下面是一组偏保守的示例值,并不是所有网站都应原样照抄:
http { client_header_buffer_size 4k; large_client_header_buffers 4 16k; # 其他配置 } |
这两个指令也可以配置在 server 上。若多个虚拟主机共用同一个监听地址,为避免请求在确定虚拟主机前使用了默认服务器的参数,统一配置在 http 层通常更容易管理;如果必须按站点设置,则要同时确认对应监听端口的默认服务器配置。
修改后先检查语法:
sudo nginx -t |
确认出现配置测试成功的提示后再平滑重载:
sudo systemctl reload nginx |
也可以使用 Nginx 自带的信号命令:
sudo nginx -s reload |
重载后重新发送原来的故障请求,并观察访问日志、错误日志和返回状态。不要只测试无痕窗口,因为无痕窗口本来就没有那组超大的 Cookie。
六、为什么不建议直接改成64k或128k
把缓冲区改得很大确实可能立刻消除报错,但这会掩盖 Cookie 无限制增长的问题,也会扩大异常请求对内存和入口资源的消耗。
Nginx 的大请求头缓冲区按需分配,请求进入 keep-alive 状态后会释放,但高并发下大量超大请求头仍然会产生额外开销。更稳妥的做法是:先测量真实请求头大小,留出合理余量,再修复业务侧的增长来源,而不是把限制无限上调。
例如,正常用户的请求头只有 3KB,异常用户却达到 30KB,那么真正应该追查的是这多出来的 27KB,而不是直接把所有入口放宽到 128KB。
七、从业务侧彻底解决Cookie膨胀
1. 不要把完整业务数据塞进Cookie
Cookie 更适合保存短小的会话标识,而不是用户资料、完整权限列表、购物车明细或大段 JSON。服务端可以只保存一个随机会话 ID,再从缓存或数据库读取实际状态。
2. 精简JWT载荷
如果必须使用 JWT,只保留鉴权需要的声明。头像地址、展示名称、完整角色描述等非必要字段不应反复随每个请求发送。还要检查令牌是否被重复包装、重复编码。
3. 检查Domain和Path
设置在 .example.com 下的 Cookie 会发送给多个子域名。若某个 Cookie 只服务于 admin.example.com,就没有必要让它跟随所有子域请求。Path 同样应尽量收窄。
删除 Cookie 时,Domain 和 Path 必须与创建时匹配。只写一个过期的同名 Cookie,却使用了不同 Path,旧 Cookie 可能仍然保留,最终造成多个同名值一起发送。
4. 修复登录流程中的状态累积
某些登录集成会在每次跳转时创建新的 nonce、state 或 correlation Cookie,流程失败后却没有清理。用户重试次数越多,请求头越大。这类问题应在认证回调、失败分支和超时清理逻辑中一起修复。
5. 检查每一层入口限制
如果架构中存在 CDN、WAF、云负载均衡、Ingress 和 Nginx,应记录每一层的请求头限制。最终可用上限由其中最小的一层决定。调整参数后也要从公网入口重新测试,不能只在源站本机使用 curl localhost 验证。
八、常见问题
清除Cookie后恢复了,还需要改Nginx吗?
不一定。先确认这是单个用户的历史残留,还是应用仍在持续写入过大的 Cookie。如果新登录用户使用一段时间后还会复现,应优先修复业务逻辑;若正常业务请求确实略高于现有限制,再适度调整 Nginx。
修改了large_client_header_buffers为什么没有生效?
常见原因有四个:配置文件没有被当前实例加载、修改后没有重载、参数写在了错误的虚拟主机、请求在到达 Nginx 前已被 CDN 或 WAF 拦截。可以结合 nginx -T、错误日志和绕过上游入口的测试逐项确认。
把Cookie拆成多个Cookie能解决吗?
通常不能。浏览器发送请求时,多个 Cookie 往往仍会组合在同一个 Cookie 请求头字段中。真正有效的方法是减少总量、缩小作用域、删除重复项,或者把状态移到服务端。
总结
处理 Nginx 的“400 Request Header Or Cookie Too Large”,最有效的顺序不是先扩大参数,而是先确认问题边界:
- 用无痕窗口和清除站点 Cookie 判断是否为用户会话问题;
- 查看 Nginx 日志,确认请求有没有到达源站;
- 在开发者工具中检查 Cookie、Authorization 和重复字段;
- 根据实测大小适度调整
client_header_buffer_size与large_client_header_buffers; - 回到应用侧清理重复 Cookie、精简 JWT,并检查 Domain、Path 和登录状态累积。
缓冲区调整解决的是“当前请求能不能进来”,Cookie 治理解决的才是“错误会不会再次出现”。两部分一起处理,才能避免同类 400 错误反复发生。
参考资料
- Nginx 官方文档:Module ngx_http_core_module
- Nginx 官方文档:Controlling nginx
- Nginx 官方文档:Beginner’s Guide
- Nginx 官方源码:ngx_http_request.c、ngx_http_special_response.c
- RFC 9110:HTTP Semantics




