nginx 1.30 升级后最容易漏掉的默认值:代理上游默认走 HTTP/1.1 并开启 keep-alive
nginx-1.30.0 stable 于 2026-04-14 发布,合并了 1.29.x mainline 的特性与修复,包括 Early Hints、到后端的 HTTP/2、Encrypted ClientHello、upstream sticky sessions、Multipath TCP,以及一项容易被升级说明淹没的默认值改动:代理到上游的 HTTP 版本默认从 1.0 变成 1.1,并默认启用 keep-alive。这个改动在 2026-03-24 的 nginx-1.29.7 中引入,1.30.0 继承下来。
配置层面看只是少写两行,运行时的连接模型却变了。
以前必须显式写的两行
要让 nginx 复用上游连接,传统写法是:
location /api/ {
proxy_http_version 1.1;
proxy_set_header Connection "";
proxy_pass http://backend;
}
proxy_http_version 的历史默认值是 1.0;如果不显式改成 1.1,nginx 还会向上游发 Connection: close,每个请求结束就断开一条上游连接,并且清空 Connection 头是配合 1.1 复用的必要动作。
1.30 起默认就是 1.1,keep-alive 开着。上面这两行在新版本里变成冗余配置;已有的 proxy_set_header Connection "" 也无害,但继续留着说明配置里还残留着旧规则的痕迹。
默认值变化带来的几个问题
上游连接不再每请求关闭
反向代理与上游之间开始维持长连接:每个 worker 缓存一批空闲连接,请求到来时优先复用。这意味着后端看到的 established 连接会持续存在,数量与 nginx 的 keepalive 池参数相关,而不是跟 QPS 一比一。
后端 idle timeout 与 nginx 不匹配会导致 502
复用的前提是连接还活着。如果后端(Tomcat、Node、Gunicorn、Go 的 IdleTimeout 等)先把空闲连接关掉,而 nginx 仍认为它可以复用,下一次请求就会落在一条已被对端关闭的连接上,日志里出现:
upstream prematurely closed connection while reading response header from upstream
或者直接返回 502。常见做法是把后端的 keep-alive 空闲超时设置得比 nginx 侧的 keepalive_timeout 略长,避免两边同时判断连接可回收。
残留的 Connection close 会把复用关掉
一些老配置模板里有:
proxy_set_header Connection close;
这行在 1.0 时代是为了规避个别后端的连接问题。默认值改成 1.1 之后,它会把新默认值带来的复用直接抵消,等于升级了但没享受到变化。要么删掉,要么改成 proxy_set_header Connection "";。
HTTP/1.0 后端与 chunked 请求体
上游只支持 HTTP/1.0 时,用 1.1 代理过去,请求体可能以 chunked 编码转发(客户端本身就用 chunked 上传时尤其明显),1.0 后端不一定认 Transfer-Encoding: chunked。这类后端需要按 location 单独回退。
确认连接是否真的在复用
先对齐配置:
nginx -V # 版本与编译参数
nginx -T # 导出完整生效配置
在 nginx -T 的输出里检索 proxy_http_version、Connection、keepalive,确认没有全局或继承下来的 close。
再看运行时:在 access log 里加上 $upstream_addr 和 $upstream_connect_time。复用已有连接时不会产生新的建连耗时,该字段通常为 -;如果每条请求都有稳定的连接时间,说明还在频繁新建连接。
log_format upstream '$remote_addr "$request" upstream=$upstream_addr '
'connect_time=$upstream_connect_time status=$status';
stub_status 的 Active connections 曲线可以看整体连接数是否随流量上升后不再回落;后端机器上用:
ss -tn state established '( sport = :8080 )' | wc -l
对照 nginx 侧的 worker 数与 keepalive 池大小,确认 established 数量落在预期区间,而不是无限增长。
需要回退时按 location 写
不要全局改回 1.0,只对不兼容的后端生效:
location /legacy/ {
proxy_http_version 1.0;
proxy_set_header Connection close;
proxy_pass http://legacy_backend;
}
在 HTTP/1.0 下 Connection: close 本来就是默认行为,写出来只是让意图更明确。
upstream keepalive 池的三个参数
默认开启 keep-alive 后,池子大小直接决定复用率与后端连接占用:
upstream backend {
server 10.0.0.11:8080;
server 10.0.0.12:8080;
keepalive 64; # 每个 worker 缓存到上游的空闲连接数
keepalive_requests 1000; # 单条连接最多处理多少个请求
keepalive_timeout 60s; # 空闲连接保持多久
}
keepalive 是每个 worker 的空闲连接缓存数量,不是总连接上限;配得太小复用率上不去,配得太大则长期占着后端连接。三个参数的准确语义与边界条件以官方文档为准。
1.30 同时进来的其他变化
除了默认代理版本,1.30 还带进了 Early Hints、到上游的 HTTP/2、Encrypted ClientHello、upstream sticky sessions、Multipath TCP 等特性,各自有独立的指令与适用条件,这里不展开。另外 2026-10-14 发布的 nginx-1.30.6 stable 与 1.31.7 mainline 修复了多个漏洞,包括 alias 配合 rewrite 的缓冲区溢出(CVE-2026-15176)、带变量的字符串表达式求值缓冲区溢出(CVE-2026-93479)、HTTP/3 请求体注入(CVE-2026-95101)、TLS session ticket key 轮换时的会话伪造(CVE-2026-97629)、ngx_http_ssi_module 配合 AIO 的 use-after-free(CVE-2026-97205),升级时直接跟到修复版本。
参考
- nginx 官方 news:
proxy_http_version指令文档: