Nginx在处理HTTP/2请求时,会先通过HPACK解码器还原出请求头列表,再使用http2_max_header_size指令检查该列表的总大小。这个检查发生在请求被传递给后端应用之前,因此一旦超限,Nginx会直接返回400 Bad Request,后端应用甚至感知不到请求内容。

一、http2_max_header_size 指令详解
http2_max_header_size 是 Nginx 提供的 HTTP/2 模块指令,用于设置经过 HPACK 解码后请求头列表的最大大小。它的语法非常简单:
http2_max_header_size size;
默认值是 16k,可以在 http 或 server 上下文进行配置。这个大小指的是所有请求头字段的名称和值总和,包括伪头字段如 :method、:path、:scheme 等。需要注意的是,它不是单个头部字段的限制,如果只想控制某个字段的长度,应该使用 http2_max_field_size。
实际场景中,Cookie 往往是头部体积膨胀的主要来源。假设一个站点的 Cookie 已经达到 14KB,再加上 User-Agent、Accept、Authorization 等常规字段,就可能超过 16KB 的默认阈值。此时无论后端语言如何处理,请求都会在 Nginx 层被拒绝。
http {
# 提升整个头部列表限制到 32KB
http2_max_header_size 32k;
# 控制单个字段最大为 8KB
http2_max_field_size 8k;
server {
listen 443 ssl http2;
server_name ippipp.com;
ssl_certificate /etc/nginx/ssl/cert.pem;
ssl_certificate_key /etc/nginx/ssl/key.pem;
...
}
}
配置完成后需要执行 nginx -t 验证语法,再通过 nginx -s reload 平滑重载。如果是在 server 上下文配置,只会对匹配该 server 的 HTTP/2 连接生效。
二、HTTP/1.1 与 HTTP/2 头部限制的本质差异
很多开发者习惯通过调整 large_client_header_buffers 来解决头部过大问题,但这条指令只对 HTTP/1.x 连接有效。HTTP/2 使用 HPACK 压缩,头部在传输前被压缩成二进制帧,Nginx 接收后先解码再校验大小,因此需要独立的 http2_max_header_size 来控制解码后的结果。
HTTP/1.1 的请求头以纯文本形式发送,每个请求头行末尾有 CRLF,Nginx 通过 large_client_header_buffers 指定缓冲区的数量和大小。例如 large_client_header_buffers 4 16k 表示最多使用 4 个 16KB 的缓冲区,单个请求头总大小不能超过 64KB。如果超限,Nginx 返回 414 Request-URI Too Large 或 400 Bad Request。
HTTP/2 的头部则被拆分为 HEADERS 帧和 CONTINUATION 帧,多个请求可以共用一个 TCP 连接,并且头部通过 HPACK 动态表进行压缩。所以实际的网络传输体积可能比解码后的头部大小小很多,但不能因为传输体积小就忽略解码后的限制。监控时应当以应用层看到的头部总大小为准。
三、定位头部超限问题
当用户报告某些请求出现 400 错误时,第一步是检查 Nginx 的 access.log 和 error.log。通常 access.log 会记录状态码 400,但不会说明具体是哪个头部超限。error.log 在默认级别下同样不会输出详细信息,需要临时将错误日志级别调整为 debug。
可以构造一个简单的超限请求来复现问题。下面的命令向服务器发送一个超过 16KB 的自定义请求头,如果返回 400,则说明 http2_max_header_size 确实被触发了。
curl -H "X-Large: $(python3 -c 'print("a" * 20000)')" https://ippipp.com/
注意,如果使用 HTTP/1.1 进行测试,这条请求可能会触发 large_client_header_buffers 的限制,而不会触发 http2_max_header_size。因此确认客户端实际协商的协议版本非常重要,可以使用 curl -I --http2 或者浏览器开发者工具查看。
除了自定义大头部,更常见的是 Cookie 和 Authorization 累积过大。可以通过浏览器开发者工具或抓包工具复制请求头,统计名称和值的总字节数,判断是否接近 16KB。
四、安全合理的配置策略
直接修改 http2_max_header_size 到 128k 或 256k 虽然能快速消除 400 错误,但也会增加拒绝服务攻击的风险。恶意客户端可以在一个 HTTP/2 连接上发送大量大头部请求,消耗 Nginx 的内存和 CPU。因此每次放大限制前,应先确认业务是否真的需要这么大的头部。
如果头部膨胀来自 Cookie,优先考虑精简 Cookie 内容。例如将大型会话数据迁移到服务端存储,只在 Cookie 中保留小型会话 ID;或者使用独立域名分发静态资源,避免不必要的 Cookie 传输。对于认证和追踪信息,也可以评估是否可以通过 HTTP/2 的服务端推送或请求体传递,而不是全部塞进头部。
如果业务确实需要较大的请求头,可以按照实际最大需求设置一个合理值,并在此基础上留出 20% 左右的余量。例如监控到最大头部为 24KB,可以设置为 32k,而不是直接拉到 128k。配置如下:
http {
# 根据实际业务峰值调整,而不是无限放大
http2_max_header_size 32k;
http2_max_field_size 16k;
# 同时限制单个连接上的最大请求数,降低资源耗尽风险
http2_max_requests 1000;
}
调整后需要持续观察 access.log 中 400 状态码的变化,并结合监控系统统计请求头大小分布。如果 400 错误消失且资源使用没有明显增长,说明配置较为合理。
五、常见误区与注意事项
一个常见误区是认为把 large_client_header_buffers 调大就能解决 HTTP/2 头部超限。实际上两者作用于不同的协议栈,HTTP/2 请求根本不会经过 large_client_header_buffers 检查,只由 http2_max_header_size 和 http2_max_field_size 共同把关。如果同时服务 HTTP/1.1 和 HTTP/2,两条限制链都要配置好。
另一个容易混淆的是 http2_max_field_size。它限制单个头部字段的名称和值之和,而 http2_max_header_size 限制整个头部列表。例如 http2_max_field_size 设置为 8k 时,即使 http2_max_header_size 是 64k,一个 10KB 的 Cookie 依然会被拒绝。反过来,多个 6KB 的字段总量超过 16KB 时,也需要调整 http2_max_header_size。
还要注意 HTTP/2 的伪头字段也计入总大小。:method、:path、:scheme、:authority 这些字段由协议自动生成,虽然通常很小,但在极端情况下长 URI 会占用较多字节。如果应用接收长查询参数,建议同时关注 request_uri 相关限制。
最后,不同 Nginx 版本对 HTTP/2 头部处理的实现可能有差异,升级到稳定版本有助于避免已知的解析缺陷。配置前建议查阅对应版本的官方文档,确认指令支持的最小值和默认值。
Nginxhttp2_max_header_sizeHTTP/2头部大小限制修改时间:2026-08-30 03:05:48