431错误源于HTTP/2下请求头总长超限,需确认启用http2、实测header字节数(如≥16KB则调大http2_max_header_size至32k)、同步配置http2_max_field_size和max_headers,并匹配后端header限制。

431 错误明确表示“请求头字段过大”,不是后端返回的,而是 Nginx 在 HTTP/2 连接解析阶段主动拒绝所致。排查必须紧扣协议类型、实际 header 体积、Nginx 多层限制和后端协同这四个关键点。
确认是否真走 HTTP/2 且触发 http2_max_header_size
这个参数只对启用了 http2 的 server 块生效。先检查配置里有没有类似这样的监听行:
-
listen 443 ssl http2;或listen [::]:443 ssl http2; - 如果只有
listen 443 ssl;,那根本用不上http2_max_header_size,问题应归到client_header_buffer_size和large_client_header_buffers - 用
curl -v --http2 https://yoursite.com看响应头是否有HTTP/2 200,再配合openssl s_client -connect yoursite.com:443 -alpn h2验证 ALPN 协商结果
实测真实请求头总字节数
别猜 JWT 多长,要测真实流量:
- 用生产环境带完整 token 的请求抓包,或用 curl 模拟:
curl -v --http2 -H "Authorization: Bearer $(cat real_jwt.txt)" https://yoursite.com/api/test 2>&1 | grep '^>' | wc -c - 注意:每行
>后的内容含 CRLF(2 字节),wc -c结果就是总 header 字节数 - 若超过 16KB(默认值),且日志出现
client sent too large header while reading header,基本锁定是http2_max_header_size不足
同步调大 HTTP/2 相关头部限制
不能只改一个参数,否则仍会 431:
-
http2_max_header_size 32k;—— 总 header 容量,JWT 较长时设为 32k 或 64k -
http2_max_field_size 32k;—— 防单个超长字段(如一个 25KB 的 Cookie),必须 ≥http2_max_header_size -
max_headers 500;—— Nginx 1.29.8+ 支持,防“大量小 header”攻击,默认 1000 行,业务稳定可降到 500~800 - 这些指令放在
http{}或具体server{}块内,改完必须执行nginx -t && nginx -s reload
检查后端是否也卡住了
Nginx 放行后,请求还会继续往后传,后端可能二次拦截:
- Node.js 启动需加
--max-http-header-size=32768 - Spring Boot 在
application.yml中配:server.max-http-header-size: 32768 - FastAPI/Uvicorn 本身不限制 header 大小,但若前面还套了 Gunicorn 或 Traefik,它们也有各自限制,需一并检查
- 验证方式:绕过 Nginx 直连后端服务,用同样长的 header 测试是否仍报 431


















