431 Request Header Fields Too Large是HTTP协议中专门用于表示请求头过大的状态码。当Nginx在读取请求头时发现某个头部字段或请求行超出了缓冲区的容量限制,就会直接返回431并中断连接。不少运维和开发人员在放大Cookie规模、接入新的网关层或上线携带大量自定义头的客户端之后,都会突然遭遇这个错误。要彻底解决它,既要理解Nginx处理请求头的内存模型,也要学会从源头控制请求头的体积。

一、431错误的产生原理与常见触发场景
HTTP状态码431在RFC 6585中定义,含义是服务器拒绝处理请求,因为请求头字段整体过大或单个字段过大,服务器不愿意(或无法)处理。Nginx返回499、400、431还是414,取决于请求在哪个环节超限。如果请求行(也就是GET加URL加协议版本这一整行)超过了缓冲区限制,Nginx会返回414 Request-URI Too Large;如果是单个请求头字段超过了限制,才会返回431。理解这个区别对定位问题很关键:如果你在日志里看到的是414,那问题出在URL太长,很可能是GET请求携带了巨大的查询参数;如果是431,重点排查的对象则是Cookie和自定义头部。
实际生产中触发431的场景主要有三类。第一类是Cookie无限膨胀,这是最普遍的原因,业务系统不断往域名下写Cookie,比如埋点、AB测试标识、登录态、防重令牌等,日积月累单是Cookie就可能达到几十KB,而Nginx默认的单个头字段上限往往只有8KB。第二类是网关或服务网格在转发请求时追加了大量内部头部,例如链路追踪信息、灰度标签、租户标识等,这些头部叠加后超出了缓冲区。第三类是配置层面的问题,有人之前为了排查414错误把large_client_header_buffers调小过,或者升级Nginx版本后配置没有跟着迁移,导致新的实例沿用了过于保守的参数。
排查时可以先看错误日志。Nginx会在error.log中记录类似client sent too long header line的日志,内容里通常会截断展示实际超长的头部开头部分,从中可以直接看出是哪个字段撑爆了请求。如果日志级别不够看不到细节,可以把error_log临时调整为debug级别复现一次,就能完整观察请求头的解析过程。
二、核心配置参数详解与调整方法
控制请求头大小的指令主要有两个:client_header_buffer_size和large_client_header_buffers。前者定义读取请求头的初始缓冲区大小,默认一般是1KB;后者定义当初始缓冲区不够时,允许申请的大缓冲区的数量和单个大小。语法为large_client_header_buffers 数量 单个大小,默认值是4 8k,也就是最多4个缓冲区,每个8KB。这里有一个容易被误解的细节:单个请求头字段(包括Cookie这种大字段)不能超过单个缓冲区的大小,而请求行也不能超过单个缓冲区大小,但所有请求头的总量理论上可以达到数量乘以单个大小的总和。
针对不同情况,调整策略也不一样。如果确认业务确实需要携带较大的Cookie或多个自定义头,可以在http、server或location级别修改配置。下面是一个典型的调整示例:
# nginx.conf 片段
http {
# 初始请求头缓冲区,适当调大可减少进入大缓冲区的概率
client_header_buffer_size 4k;
# 大缓冲区:4个,每个16k
# 单个头字段(如Cookie)最大允许16k
large_client_header_buffers 4 16k;
# 读取请求头的超时时间,头太大时客户端发送慢可能触发超时
client_header_timeout 30s;
}
调整之后务必用nginx -t验证配置语法,再通过nginx -s reload平滑生效。参数设置的大小建议参考实际观察到的最大请求头体积再留出余量,比如线上观察到最大的Cookie约12KB,那么单个缓冲区设为16K比较稳妥。不建议一上来就设成128k这种夸张的值,原因在下一节展开。另外要注意,如果Nginx前面还有CDN、云负载均衡或别的代理层,431也可能由那一层返回,需要确认错误响应头中的Server字段,判断到底是哪一层的限制被触发,避免改了半天Nginx结果问题出在网关上。
三、盲目调大缓冲区的风险与治本方案
把large_client_header_buffers调大虽然能立竿见影,但这是典型的治标方案。风险主要在两方面:一是内存占用,Nginx的这些缓冲区是在处理连接时按需分配的,调大之后每个活跃请求都可能占用更多内存,在连接数高的场景下内存压力会明显上升,极端情况下可能触发OOM;二是安全面,允许超大请求头意味着攻击者可以用很小的成本发送巨大的头部消耗服务器资源,等于主动放宽了攻击面。原本Nginx默认的8K限制,某种程度上就是一道天然的防护墙。
更值得做的治本工作是从源头瘦身请求头。首先是清理Cookie:检查业务里是否有废弃的埋点、过期实验的标识、重复的登录态,把不再使用的键彻底删掉;Cookie的Domain和Path属性也要收敛,避免所有子域共享一个越滚越大的Cookie。其次是把客户端到服务端的元数据从Cookie迁移到别处,比如非敏感的偏好类数据可以放在localStorage里按需携带,登录态用短令牌替代长会话串。最后是网关层头部的治理,规定内部透传头必须有白名单,定期审计有没有陈年的调试头一直被转发。
此外还可以在接入层增加监控与防护的组合拳:通过$request_length变量统计请求总大小并接入告警,一旦出现异常增长能第一时间发现;配合limit_req模块对高频大请求做速率限制;对于明显是扫描器的畸形请求,直接依靠默认缓冲区限制拒绝即可,不必为其放宽配置。总结成一句话:调整缓冲区解决眼前的431是必要的应急手段,但长期应该把请求头体积控制在合理范围内,配置参数与请求治理两条腿走路,才能既保证业务可用又不牺牲服务器的稳定性与安全性。
Nginx 431Request Header Fields Too Largelarge_client_header_buffers修改时间:2026-09-08 18:23:03