在Nginx的HTTP2模块中,http2_push_diary_values是一个容易被忽略但非常实用的指令。它决定了服务端推送(server push)过程中,日记(diary,此处指Nginx内部记录推送相关上下文的调试或访问日志扩展)里具体记录哪些值。很多同学在调试推送为什么没生效时,往往只盯着http2_push指令本身,却不知道推送日记里的线索需要通过这个指令来开启和过滤。

一、http2_push_diary_values的底层原理与取值类型
Nginx在处理HTTP2请求时,会为每一个推送流(push stream)构建一个内部的上下文结构。这个结构里原本就携带了请求头、连接信息、推送优先级等数据。http2_push_diary_values的作用,就是告诉Nginx在写日记时,从这些上下文中挑选哪些字段落盘。它的语法形式为:http2_push_diary_values off | on | string ...;。其中string部分可以填写多个用空格分开的变量名或头部名。
当取值为off时,Nginx完全不会为推送流写任何扩展日记,这是默认行为,目的是节省IO。当取值为on时,Nginx会把所有可用的请求头及内部变量都记录下来,日志量较大,但适合初期抓全量问题。当取值为具体的头部列表,例如http2_push_diary_values authorization user_agent;,则只记录这些指定头部的值。这种机制本质上是日志精细化的体现,和log_format定制字段的思路一致,只是作用域限定在HTTP2推送。
从实现上看,Nginx在ngx_http_v2_module中定义了该指令的解析函数,会把用户给出的字符串列表注册到一个配置数组中。每次推送创建时,日记模块遍历这个数组,从r->headers_in或r->variables里取值并写入缓冲区。因此如果填写了不存在的头部名,Nginx会在配置解析阶段报“unknown diary value”并拒绝启动,这是常见的配置错误来源。
二、不同取值下的配置示例与对比分析
下面给出三组典型配置,分别展示关闭、全开和指定字段三种写法。第一组是完全关闭,适合生产环境对性能敏感的场景:
http {
server {
listen 443 ssl http2;
# 完全不记录推送日记
http2_push_diary_values off;
location / {
root /var/www/html;
http2_push /style.css;
}
}
}
第二组是开发调试时全开,可以拿到最完整的推送上下文。注意这会显著增加磁盘写入,不能在高压生产环境长期使用:
http {
server {
listen 443 ssl http2;
# 记录所有可推送日记值
http2_push_diary_values on;
location / {
root /var/www/html;
http2_push /app.js;
http2_push /logo.png;
}
}
}
第三组是指定关键头部,平衡了排查需要与性能开销。比如我们只关心用户身份和客户端类型,就可以只写这两个:
http {
server {
listen 443 ssl http2;
# 只记录授权头和UA
http2_push_diary_values authorization user_agent;
location / {
root /var/www/html;
http2_push /main.css;
}
}
}
通过对比可以发现,off适合稳定期,on适合排查复杂推送失败,而列表模式适合常态化轻度监控。在真实项目中,如果推送资源总是不生效,先用on抓一次日志,看到底有没有触发推送流,再缩窄到具体字段,是最高效的路径。
三、常见误区与基于日记值的排错思路
一个常见误区是以为http2_push_diary_values能控制是否推送,实际上它只控制“记录什么”,不控制“推不推”。推送本身由http2_push和http2_push_preload决定。有人配置了推送但浏览器没收到,查日记发现是off导致无任何线索,就误以为是指令失效,这是概念混淆。
另一个误区是填写了非头部字符串,例如直接写$request_time这种变量符号。Nginx要求此处填的是头部名(如user_agent)或内部支持的特定关键字,带美元符号的写法会解析失败。正确方式应省略美元符,仅写变量基础名,具体支持列表可查阅对应版本源码里的ngx_http_v2_diary_variables数组。
排错时,建议先设成on并重载,然后访问触发推送的页面,在日志中搜索“push diary”相关行。如果日记里出现了push stream created但浏览器未收,可能是客户端不支持或已缓存;如果日记里根本没有对应值,说明推送指令未匹配到路由。通过http2_push_diary_values拿到的精确字段,我们能快速区分是配置层、网络层还是客户端层的问题,而不必盲目改动推送路径。
Nginxhttp2_pushdiary_values修改时间:2026-08-16 15:58:17