在Nginx里配置HTTP/2 Server Push时,网上有些教程会出现http2_push_diary_ttl_unit这个参数,并且告诉大家要配上s或者ms来指定时间单位。但实际一查Nginx官方文档,无论是最新主线还是稳定分支,都找不到这个指令。出现这种情况一般有两种可能:一是你用的Nginx是加了HTTP2 Push增强补丁的定制版本,二是有人把某个内部参数名误写成了配置指令。要避免被带偏,就得从HTTP/2 Push的记录机制出发,搞清楚这个ttl到底控制什么、单位该怎么判断。

一、http2_push_diary_ttl_unit不属于Nginx官方指令
Nginx官方提供的HTTP/2 Server Push能力来自ngx_http_v2_push_module模块,这个模块只开放了两个核心配置项:http2_push和http2_push_preload。http2_push可以在http、server或location上下文中指定需要主动推送的URI,比如把它放在location /里,就能在客户端请求主文档时同时推送样式表和脚本文件。http2_push_preload则用来配合后端Link响应头,让Nginx自动推送后端标记为preload的资源。
无论是稳定版还是主线版本,官方模块都没有提供任何与TTL相关的配置。也就是说http2_push_diary_ttl_unit这个写法不可能出现在纯净Nginx环境中并成功生效,除非你使用的是第三方分支或者额外编译了某个HTTP2 Push管理模块。很多定制版会扩展diary机制,用TTL控制已推送记录的生命周期,同时再用一个unit参数指定时间单位。判断自己环境是否支持,最直接的办法是执行nginx -V查看编译参数,如果看到类似add-module=/path/to/http2_push_module这样的内容,说明模块是外部引入的。
下面这段配置是官方HTTP2 Push的标准用法,它不涉及任何TTL,只在location中写出需要推送的资源路径。
server {
listen 443 ssl http2;
server_name ipipp.com;
ssl_certificate /etc/nginx/ssl/cert.pem;
ssl_certificate_key /etc/nginx/ssl/key.pem;
location / {
http2_push /style.css;
http2_push /app.js;
http2_push_preload on;
root /var/www/html;
}
}
二、时间单位如何影响Push Diary的TTL行为
理解了配置来源之后,再看时间单位就清楚得多。Nginx为了不让同一个连接反复推送相同的资源,内部会维护一个已经推送过的URL集合,不同实现里叫push diary或push cache。当一个资源被PUSH_PROMISE帧推送出去后,这个URL会被写入diary,后续即使用户再次触发推送条件,Nginx也会先查diary,如果命中就跳过推送。TTL就是这些记录的有效期,到期后记录被清除,后续如果条件再次满足,资源可以重新推送。
时间单位直接决定了TTL数值的解读方式。假设模块允许设置http2_push_diary_ttl 60,后面再用http2_push_diary_ttl_unit指定单位。如果单位是s,那么记录保留60秒;如果单位是ms,那么60就表示60毫秒,记录几乎瞬间失效;如果单位是min,60表示60分钟,记录会停留很久。单位搞错最典型的后果有两个:一是推送记录长期不失效,导致用户在单次长连接里永远收不到二次推送;二是记录过早失效,本应避免的重复推送频繁发生,反而浪费流量。
不同模块对单位字符串的定义并不统一,有的模块只接受s和ms,有的扩展了min甚至h。遇到这类非标准指令,不要靠猜,应该先找到模块的README或源码。下面是一段常见的配置解析示例,说明模块在解析单位字符串时可能采用什么样的枚举定义。
static ngx_conf_enum_t ngx_http2_push_diary_ttl_unit_values[] = {
{ ngx_string("s"), 1 },
{ ngx_string("ms"), 1000 },
{ ngx_string("min"), 60 },
{ ngx_null_string, 0 }
};
三、判断当前环境是否支持该指令以及验证方法
判断环境是否支持http2_push_diary_ttl_unit,第一步永远是查看编译参数和模块版本。可以在服务器上执行nginx -V,把所有输出仔细看一遍。注意configure arguments这一行通常会列出所有非官方模块的路径,找到与push相关的模块名后,再去该模块的文档里确认参数。另一个更快的办法是直接跑nginx -t,如果配置中写了http2_push_diary_ttl_unit但Nginx不认识这个指令,检测阶段就会报unknown directive错误。如果没报错,至少说明配置被正常解析了。
验证时间单位是否正确,要结合HTTP2帧级的抓取工具。浏览器开发者工具里也可以看到Server Push信息,但nghttp更直观。先用nghttp访问一次站点,观察输出中是否有PUSH_PROMISE帧;然后等待一个比TTL稍长的时间,再次访问同一个站点,看是否重新出现推送帧。如果TTL为2秒,那么第一次和第二次间隔3秒就应该重新推送;如果间隔3秒后还是没有推送,说明单位可能被当成了分钟或者配置没有生效。
下面的命令可以快速确认Nginx编译信息、配置语法以及HTTP2推送帧。
nginx -V 2>&1 | grep push nginx -t nghttp -ans https://ipipp.com/
四、遇到非标准指令时的处理思路
如果你正在维护一个使用了http2_push_diary_ttl_unit的Nginx环境,又找不到模块文档,最稳妥的做法是先用最小配置验证时间单位。把TTL设成一个很小的值,比如2,再分别用s和ms尝试,观察推送行为差异。如果设置2s后能稳定复现两秒过期,说明单位就是秒;如果设置2ms也能观察到几乎立即过期,说明模块接受毫秒。这种逆向验证比翻源码更快,也避免了因文档缺失导致的错误配置。
对于需要迁移到标准Nginx的项目,建议放弃这些非标准TTL参数,改用官方提供的http2_push和http2_push_preload来管理推送。官方方案虽然没有TTL微调,但通过http2_push_preload配合后端Link头,可以让推送决策由应用层控制,反而更清晰。比如后端可以在响应头中动态输出Link: </style.css>; rel=preload; as=style,Nginx会自动推送,即使迁移到别的环境也保持兼容。
最后提醒一点,HTTP2 Server Push目前在Chrome等浏览器中已经逐渐被弃用,新项目如果过度依赖Push可能得不偿失。理解这些配置的时间单位固然重要,但更值得思考的是何时该用Push、哪些资源值得推。把TTL和时间单位搞清楚,至少能保证你的Push策略不会因为配置错误而失效。
Nginx HTTP2 Server Pushhttp2_push_diary_ttl_unit时间单位修改时间:2026-09-21 01:54:32