导读:本期聚焦于俊华创作的《Nginx如何配置HTTP/2 Push并结合log_format记录推送日志?》,敬请观看详情。Nginx的HTTP/2 Push允许服务端在客户端请求HTML之前主动推送CSS、JS等静态资源,从而减少往返延迟。但推送是否生效、命中率如何,需要通过自定义日志格式来验证。本文将围绕http2_push指令的配置方法展开,讲解如何在http2 server块中声明推送资源,重点介绍如何利用Nginx内置的http2相关变量,比如http2_pushed、http2等,结合log_format指令编写专门的推送日志格式,帮助你判断哪些请求是被动推送出去的资源、哪些推送其实被客户端拒绝,并分析推送策略的适用场景与注意事项,例如RST_STREAM导致推送浪费的问题。文末给出可直接复用的完整配置示例。

HTTP/2的服务端推送是一项颇具争议的特性,它允许服务器在浏览器明确请求CSS、JS之前,把资源顺着同一条连接提前推过去。Nginx从1.13.9版本开始原生支持这项功能,配置方式非常简单,但很多开发者配完之后根本不知道推送有没有真正生效,客户端到底是接收了推送还是直接发了RST_STREAM拒绝。这就需要借助自定义的日志格式来观察。本文把http2_push和log_format两块配置结合起来讲,帮你把推送行为完整地记录下来。

Nginx如何配置HTTP/2 Push并结合log_format记录推送日志?

一、http2_push的基础配置

Nginx提供了两个核心指令:http2_pushhttp2_push_preload。前者直接指定要推送的资源路径,后者则解析响应头中Link字段的preload提示并自动转为推送。两者可以并存,但更推荐用preload方式,因为它的语义是标准化的,客户端不支持HTTP/2推送时也能退化为预加载。

一个典型的server配置如下:

server {
    listen 443 ssl http2;
    server_name example.ipipp.com;

    ssl_certificate     /etc/nginx/ssl/server.crt;
    ssl_certificate_key /etc/nginx/ssl/server.key;

    root /var/www/html;

    location = /index.html {
        http2_push /style.css;
        http2_push /app.js;
        http2_push_preload on;
    }
}

需要注意,http2_push只能出现在location上下文中,且推送的资源路径必须是URI形式。Nginx会在发送主资源响应的同时,通过PUSH_PROMISE帧告知客户端即将推送的内容。如果客户端不想要这些资源,会立刻发送RST_STREAM取消,但此时服务器可能已经读取了文件甚至占用了带宽,这就是推送被滥用后反而降低性能的原因。

二、用log_format记录HTTP/2推送行为

Nginx内置了两个与HTTP/2直接相关的变量:$http2表示协商出的HTTP协议版本(值为2表示h2,空表示HTTP/1.1),$http2_pushed则标记当前请求是否由服务端推送产生,值为on表示这是一个被推送出去的资源请求。利用这两个变量,我们可以在http块中定义专门的日志格式:

http {
    log_format push_diary '$remote_addr - $remote_user [$time_local] '
                           '"$request" $status $body_bytes_sent '
                           'proto=$http2 pushed=$http2_pushed '
                           'referer="$http_referer" '
                           'ua="$http_user_agent" '
                           'rt=$request_time urt=$upstream_response_time';

    access_log /var/log/nginx/push_diary.log push_diary;
}

这样配置之后,每次访问index.html产生的日志里,被推送的style.css和app.js行会出现pushed=on,而未被推送的普通请求则显示pushed=-。通过简单的grep统计就能算出推送命中率:

grep 'pushed=on' /var/log/nginx/push_diary.log | wc -l
grep 'proto=2' /var/log/nginx/push_diary.log | awk '{print $9}' | sort | uniq -c

如果想进一步区分推送是否被客户端接受,可以结合$status观察:正常完成的推送返回200,而被RST_STREAM中断的推送在部分版本中会表现为499或其他非标准状态码。虽然Nginx没有直接暴露客户端取消推送的专用变量,但结合推送日志与浏览器DevTools的Network面板交叉验证,基本可以还原完整的推送链路。

三、按条件输出推送日志与常见坑

生产环境中不建议让所有请求都写入push_diary格式,可以用map配合条件日志降低开销。例如只对推送产生的请求单独记录:

map $http2_pushed $push_log_flag {
    default 0;
    on      1;
}

server {
    listen 443 ssl http2;
    access_log /var/log/nginx/push_diary.log push_diary if=$push_log_flag;

    location / {
        http2_push_preload on;
        root /var/www/html;
    }
}

这里用到了access_log的if参数,只有变量值为非空且不为0时才写日志,非常适合推送量大的站点做采样分析。

最后提醒几个实践中的注意点。第一,Chrome从106版本起已默认禁用HTTP/2 Push,如果你的主要用户是Chrome,推送基本不会命中,此时应改用103 Early Hints或Preload头,nginx 1.21.4以上可通过early_hints指令支持前者。第二,推送资源必须是同源的,且不能是已经缓存的资源,否则客户端会直接取消,白白浪费带宽。第三,日志变量$upstream_response_time在纯静态推送场景下为空,不要在告警脚本里依赖它做判断。把推送日志跑上一周,统计出真实的命中率,再决定是保留、调整还是彻底下线http2_push,这才是用数据驱动配置优化的正确姿势。

Nginxhttp2_pushlog_format修改时间:2026-09-05 05:28:37

免责声明:已尽一切努力确保本网站所含信息的准确性。网站作品多为原创整理与精心创作,观点力求客观中立。本站旨在免费分享,内容仅供个人学习、研究或参考使用。若引用了第三方作品,版权归原作者所有。如内容涉及您的权益,请联系我们进行处理Email:chomcom@qq.com。
引用或转载本作品时,请注明当前出处:https://www.ipipp.com/html/20260905/50701.html,基于非商业用途的前提下,欢迎转载或二创本作品。
内容垂直聚焦
专注技术核心技术栏目,确保每篇文章深度聚焦于实用技能。从代码技巧到架构设计,为用户提供无干扰的纯技术知识沉淀,精准满足专业提升需求。
知识结构清晰
覆盖从开发到部署的全链路。AI、前端、编程、数据库、服务器、建站、系统层层递进,构建清晰学习路径,帮助用户系统化掌握开发与运维所需的核心技术。
深度技术解析
拒绝泛泛而谈,深入技术细节与实践难点。无论是数据库优化还是服务器配置,均结合真实场景与代码示例进行剖析,致力于提供可直接应用于工作的解决方案。
专业领域覆盖
精准对应开发生命周期。从前端界面到后端编程,从数据库操作到服务器运维,形成完整闭环,一站式满足全栈工程师和运维人员的技术需求。
即学即用高效
内容强调实操性,步骤清晰、代码完整。用户可根据教程直接复现和应用于自身项目,显著缩短从学习到实践的距离,快速解决开发中的具体问题。
持续更新保障
专注既定技术方向进行长期、稳定的内容输出。确保各栏目技术文章持续更新迭代,紧跟主流技术发展趋势,为用户提供经久不衰的学习价值。