后台列表页做了批量导出,前端把勾选的几十个 id 拼在 GET 参数里,点一下浏览器直接出来一行 414 Request-URI Too Large,nginx 的默认错误页,连日志都没进业务代码。
414 是谁返回的
nginx 解析请求行时有缓冲区上限,默认 large_client_header_buffers 4 8k,请求行加上头部超过这个尺寸就直接拒掉。此时请求根本没到 PHP 或 Java 那边,业务日志里自然什么都看不到。
先想业务上要不要这么长
GET 参数塞几十个 id,URL 长度很快就破两千字符,浏览器、代理、CDN 各有一层限制,就算 nginx 放行了,中间任何一环都可能截断。正确做法是改成 POST 提交,或者前端分批请求,每批二十条。分页参数、筛选条件也尽量简短。
确实要调的话改哪
在 http 或 server 块里把 large_client_header_buffers 调到 4 16k,client_header_buffer_size 保持 4k 左右,nginx -t 检查后 reload。数值别一路加到 64k,超长请求头是常见的攻击手法,缓冲区越大越吃内存。
顺手看一眼是不是被扫
- 访问日志里同一 IP 大量超长 URI,基本是在探测
- 配合 limit_req 限制请求速率
- 返回 414 的请求也建议记一条日志,方便回溯
改完怎么验证生效
nginx -t 只会检查语法,真正生效看响应头。curl -I 一个故意超长的地址,看返回码是不是还是 414。也可以用 curl 加参数试:-H 拼一个 12k 的 X-Test 头,改之前直接 400 或 414,改之后能进到业务。浏览器缓存和前面一层 CDN 也要一起看,阿里云、腾讯云的 CDN 默认对 URL 长度有自己的上限,源站调大了不代表链路通。
PHP 那边还有两个值别忘了:client_max_body_size 默认 1m,改 POST 之后一次提交大量 id 很容易撞上 413;fastcgi_read_timeout 默认 60 秒,导出任务跑得久要一起调。
我的处理习惯是先改前端传参方式,缓冲区只作为兜底。只调 nginx 不改业务,下一次数据量更大照样报错。