LOGO 首页 OA教程 ERP教程 模切知识交流 PMS教程 CRM教程 技术文档 其他文档  
 
网站管理员

[点晴永久免费OA]Nginx 1.31.5来了,炸出4个硬核特性:告别信号控进程,原生JSON解析来了

admin
2026年9月10日 15:9 本文热度 241
​2026 年 9 月 2 日,Nginx 官方发布主线版本 1.31.5。官网首页只用一句话概括了这次更新:主打 Control API、predicate locations、ngx_http_json_module 三大特性。

但很少有人注意到,这次更新还藏着一个关键指令client_body_early_read,正是它把前三者串成了完整的能力闭环。

更值得关注的是发布节奏:从 8 月 19 日的 1.31.4 到这次更新仅隔两周,却一口气放出 4 个新特性,这在 Nginx 历史上并不常见。前两个版本分别以安全修复和 Bug 修复为主,而 1.31.5 显然是攒了一批能力的集中释放。

这篇我们把四个新特性拆透:它解决了什么真实痛点、语法怎么用、有哪些必须避开的坑。所有结论均来自官方CHANGES 文档与正式规范。

一、Control API:Nginx终于不用只靠信号控制了

很多人看到「Control API」会联想到商业版的ngx_http_api_module,但两者完全不是一回事:商业版 API 跑在 worker 进程里,是 HTTP 模块;而 1.31.5 的 Control API 实现在master进程中,定位天差地别。

对准运维痛点的4个端点

按照官方 OpenAPI 规范,目前只有 4 组核心端点,但每一个都戳中了运维的日常痛点:

  • GET /1/control/config:返回内存中实际生效的完整配置,包含所有include 进来的文件。彻底解决「线上跑的到底是哪份配置」的灵魂拷问,磁盘文件改了没reload、配置系统覆盖过,以前全靠流程和记忆,现在一个请求拿到进程内的真相。

  • PATCH /1/control/config:触发配置重载,等价于nginx -s reload。但比信号强的是:重载成功返回200,失败返回422,失败原因直接写在响应体的 logs 字段里。以前发reload 信号,命令秒返回,成功与否得去翻错误日志,重载失败还会静默回滚,自动化脚本极难感知。现在有了明确的状态码和返回信息,运维自动化的可靠性直接上一个台阶。

  • GET /1/control/processes:返回所有 worker 进程的名称、PID、以及exiting退出状态布尔值。以前排查平滑重载,得去ps 里grep 进程名字符串判断旧worker 是否退完;现在直接拿结构化字段做告警:reload后 5分钟仍有exiting=true 的worker,就说明有长连接迟迟未释放。

  • GET /1/nginx:返回版本与 build 标识。

启用方式与安全红线

Control API 不能通过配置文件开启,必须通过命令行参数指定监听地址:

sudo nginx -l unix:/tmp/nginx.sock

支持 UNIX 域套接字或 TCP 端口,编译时需要加--with-control-api参数。

安全是这里的重中之重:官方明确警告「永远不要把 Control API 暴露到公网」。它能导出完整的配置文件,里面的内网后端地址、证书路径、服务拓扑全是敏感信息;再加上能触发配置重载,一旦被利用就是完整的攻击链。

最推荐的用法是优先用UNIX域套接字,权限直接交给文件系统控制,默认只有运行 Nginx 的用户能访问,比 TCP 层面做 ACL 可靠得多。

信号不会被取代,但分工变了

Control API 没有覆盖信号的全部能力,比如二进制热升级、日志轮转依然靠信号。它补上的是「可编程」和「可观测」两块短板:需要脚本化、需要明确返回值、需要查询状态的场景用API;日志轮转、热升级这类成熟工具链的场景继续用信号

二、Predicate Locations:location匹配第一次跳出URI限制

Nginx 的 location 匹配规则十几年来没变过:前缀匹配、正则匹配、精确匹配、阻断正则。所有规则都有一个共同前提:只对请求URI做匹配

想实现「Content-Type 是 json 走这套配置」「查询参数带 version=v2 走另一个后端」,以前要么在 location 里写 if,要么用 map 生成变量后逐个引用。1.31.5 给出了第三条路:predicate locations。

语法与匹配逻辑

语法非常简单,变量前加$前缀即可:

location   $variable { ... }

匹配规则:变量的值不为空、且不等于0,则匹配成功,和 Nginx 里 if 指令的真值判断完全一致,学习成本几乎为零。

优先级顺序

这是使用前必须搞清楚的核心点,1.31.5 之后完整的匹配流程是:

1.检查所有前缀 location,记下最长匹配的结果,但不生效;

2.按配置顺序检查正则 location,第一个匹配的直接生效,搜索终止;

3.没有正则匹配的话,按顺序检查 predicate locations,第一个匹配的生效;

4.都没匹配上,才用第一步记下的最长前缀 location。

简单说:predicate优先级低于正则,高于前缀。另外^~的阻断能力对 predicate 同样有效,精确匹配命中后也不会再检查 predicate。

为什么它比if更值得用

社区流传多年的「If is Evil」不是空话:if 属于 rewrite 模块,执行阶段和 location 匹配完全不同,内部指令的继承规则反直觉,和 proxy_pass、try_files 组合时经常出现难以调试的诡异行为。

而 Predicate location 是location匹配阶段的原生组成部分,和普通 location 遵循完全相同的配置继承规则。你在里面写的任何指令,行为都和写在普通 location 里完全一致,这是本质上的优势,不止是语法好看。

一个容易踩的坑

如果在 predicate location 里用 alias,它的值必须是完整文件路径,不能像前缀location 那样自动拼接URI 后缀。因为predicate 匹配的是变量,和URI 没有对应关系,自然不存在「去掉前缀剩下的部分」。没注意到这点的话,表现就是静态文件404,排查还容易跑偏到权限和路径拼写上去。

三、ngx_http_json_module:不用Lua也能原生解析JSON了

Nginx 一直把请求体当不透明的字节流,只负责转发不关心内容。纯反向代理时代没问题,但到了 API 网关场景,基于请求体做路由、鉴权、审计都是刚需。

过去只能引入 lua-nginx-module 或者 njs,等于在 Nginx 里塞进一门脚本语言,带来运行时开销、调试复杂度和维护成本。1.31.5 终于带来了原生解决方案。

核心指令json_set

模块核心是json_set指令,写在 http 块中全局声明:

json_set   $variable $source path;

$source是持有 JSON 文本的变量,path是提取路径,结果赋值给$variable。路径用点号分隔对象成员,方括号加零基索引访问数组:

json_set   $user_name $request_body user.name;
json_set $tag0 $request_body tags[0];

很容易被忽略的一点:JSON不一定要来自请求体,查询参数、自定义变量里的JSON 都能解析,灵活性很高。

关键规则与性能设计

  • 字符串会去转义后存储,数字、布尔值、null 按原样存为字符串;

  • 路径不存在时变量处于 not found 状态,而非空字符串;

  • 源变量为空、不合法、JSON 不完整,所有从它提取的变量全部失效。

性能上官方明确:一份JSON每个请求只解析一次,解析发生在第一次访问对应变量的时候。也就是说你写十几条json_set 也只会解析一次,没用到的请求完全不会产生解析开销,惰性设计非常友好。

另外json_max_depth默认 32 层,既防递归解析攻击,也足够绝大多数 API 场景使用。

四、client_body_early_read:串起所有特性的关键一环

这个指令看起来最不起眼,但却是让前面几个特性真正能用起来的核心。

Nginx 默认按需读取请求体:哪个模块需要什么时候读。但 json_set 要从 $request_body 取值,predicate location 又在请求处理极早期执行,按默认时机,location 匹配的时候请求体根本还没读,变量自然是空的。

client_body_early_read就是解决这个时序问题的。

语法与条件启用

client_body_early_read   string ...;

接受一个或多个参数,只要有一个参数的值不为空且不为 0,就启用提前读取。接收完请求头之后立即读取请求体。

最典型的用法是配合 map,只对 JSON 请求提前读,其他请求维持默认行为,避免不必要的开销:

map  $http_content_type $is_json {
   application/json  1;
}
server {
  client_body_early_read $is_json;
}

两条硬性不兼容限制

  • 和无缓冲请求体的模块不兼容,典型是 gRPC 模块。gRPC 是流式传输,不存在「读完」的时刻,和提前读取语义直接冲突。

  • 和把请求体写入文件的模块不兼容,典型是 DAV 模块。提前读取时client_body_in_file_only指令会被静默忽略,不会报错,排查起来非常困难。

如果同个 server 里既有 gRPC 又有 JSON 解析,一定要用条件变量隔开,确保 gRPC 请求不会触发提前读取。

四个特性组合,纯配置实现动态路由

单独看每个特性都只是补短板,但组合起来就能实现过去必须写 Lua 才能做的事:纯配置完成基于请求体内容的动态路由。

最简实现示例:

map   $http_content_type $is_json {
    application/json  1;
}
http {
    json_set $target_env $request_body   deployment.target;
    json_set $user_id    $request_body user.id;
    server {
        listen 8000;
        client_body_early_read  $is_json;
        location $target_env {
            proxy_pass   http://$target_env-backend;
            proxy_set_header X-User-Id   $user_id;
        }
        location /api/ {
            proxy_pass   http://default-backend;
        }
    }
}

请求头收完先判断是否是 JSON,是就提前读请求体;location 匹配阶段触发 JSON 解析,取出目标环境字段;predicate 匹配成功后代理到对应后端,同时把用户 ID 透传过去。全程没有脚本运行时,纯配置搞定。

两个影响重大的Bug修复

除了新特性,这次更新的 Bug 修复里有两个值得重点关注:

1.HTTP/2代理场景下的use-after-free开启代理缓冲时,向HTTP/2 客户端发响应过程中出错,可能触发worker 进程内存访问异常。这恰好是当下最主流的部署形态,低负载可能没事,高并发生产环境风险很高,是升级的充分理由。

2.worker耗尽文件描述符后无法退出优雅关闭前如果耗尽了文件描述符,worker可能卡住不退出。在K8s 滚动更新场景下,这会导致Pod 等到终止宽限期结束后被强杀,存量连接硬中断,滚动更新出现请求失败。而且日志里的报错看起来像网络问题,非常有迷惑性。

升级前必须确认的5件事

  1. 编译参数:Control API 和 JSON 模块需要显式编译开启(--with-control-api、--with-http_json_module);predicate locations 和提前读取指令在核心模块里,无需额外编译。

  2. 版本定位:1.31.x 是主线版本,不是稳定版。新特性首次发布,边界情况没有经过大规模生产验证,追求稳定的生产环境请谨慎评估。

  3. Control API 暴露面:优先用UNIX 套接字,必须用TCP 的话先配好防火墙规则再启用。完整配置泄露的后果是整个内网拓扑暴露。

  4. 兼容性排查:检查现有配置里的 gRPC、DAV 模块,确保不会误触发提前读取;同时确认是否依赖client_body_in_file_only,它会被提前读取静默失效。

  5. predicate里的 alias:如果在 predicate location 中提供静态文件,记住 alias 要写完整路径,不要按前缀 location 的经验来写。


该文章在 2026/9/10 15:15:07 编辑过
关键字查询
相关文章
正在查询...
点晴ERP是一款针对中小制造业的专业生产管理软件系统,系统成熟度和易用性得到了国内大量中小企业的青睐。
点晴PMS码头管理系统主要针对港口码头集装箱与散货日常运作、调度、堆场、车队、财务费用、相关报表等业务管理,结合码头的业务特点,围绕调度、堆场作业而开发的。集技术的先进性、管理的有效性于一体,是物流码头及其他港口类企业的高效ERP管理信息系统。
点晴WMS仓储管理系统提供了货物产品管理,销售管理,采购管理,仓储管理,仓库管理,保质期管理,货位管理,库位管理,生产管理,WMS管理系统,标签打印,条形码,二维码管理,批号管理软件。
点晴免费OA是一款软件和通用服务都免费,不限功能、不限时间、不限用户的免费OA协同办公管理系统。
Copyright 2010-2026 ClickSun All Rights Reserved  粤ICP备13012886号-9  粤公网安备44030602007207号