HTTP/2 Server Push曾经被视为提升页面加载性能的利器,它允许服务器在客户端请求HTML之前,主动把CSS、JS等关键资源推送到浏览器。但在实际使用中,如果不做任何去重控制,服务器可能在每次请求时都重复推送相同资源,造成带宽浪费甚至性能倒退。Nginx针对这个问题提供了http2_push_diary指令,也就是推送日记机制。本文将围绕http2_push_diary的取值、原理和配置实践展开详细讲解。

什么是http2_push_diary,它的值代表什么
http2_push_diary是Nginx中用来记录“已经向当前连接推送过哪些资源”的一个位图缓存。指令的基本语法是http2_push_diary max_entries;,其中max_entries表示日记中最多能记录多少条资源条目。这个值必须是2的幂次方,例如128、256、默认值是256。需要注意的是,Nginx 1.25.1之后的版本已经废弃了HTTP/2推送相关的全部指令,因为Chrome等主流浏览器已经宣布放弃对Server Push的支持,如果你使用的是较新版本的Nginx,配置这些指令时会收到废弃警告。
推送日记本质上是一个布隆过滤器(Bloom Filter)风格的位图结构。Nginx会对待推送资源的URL做哈希计算,然后映射到位图中的某一位。当同一个HTTP/2连接上再次准备推送相同资源时,Nginx会先查询日记,如果该资源对应的位已经被标记,就跳过推送。这种设计的好处是查询开销极小,内存占用也非常低,256个条目通常只需要几十字节的内存。
需要特别理解的一点是:推送日记是基于单条HTTP/2连接的,不是基于浏览器缓存的全局记录。也就是说,如果客户端关闭连接后重新建立连接,日记会被清空,之前推送过的资源可能会被再次推送。为了避免这种情况,浏览器会在请求头中携带SHA-256摘要格式的推送日记,告知服务器哪些资源已经在本地缓存,Nginx会将这份信息合并到自己维护的日记中,从而实现跨连接的去重。
http2_push_diary的取值分析与推荐配置
max_entries的取值直接影响日记能追踪的资源数量。取值过小会导致哈希冲突概率上升,某些未推送的资源可能被误判为“已推送”而漏推;取值过大则会浪费少量内存。下面是一个典型的生产配置示例:
server {
listen 443 ssl http2;
server_name www.ipipp.com;
# 开启推送日记,记录最多512个资源条目
http2_push_diary 512;
# 方式一:显式推送静态资源
http2_push /css/main.css;
http2_push /js/app.js;
# 方式二:通过Link头自动推送,配合preload使用
http2_push_preload on;
ssl_certificate /etc/nginx/ssl/server.crt;
ssl_certificate_key /etc/nginx/ssl/server.key;
}
一般而言,对于普通的内容型网站,页面依赖的关键资源通常在20个以内,默认的256已经绰绰有余。如果你的站点是大型单页应用,首屏可能加载上百个模块文件,可以考虑将值调整为512或1024。由于该值必须为2的幂次方,设置为100、300这样的非规范值会导致Nginx在启动时报配置错误。
另外要注意http2_push_diary与http2_push_preload的配合关系。当开启preload模式后,Nginx会解析上游应用返回的Link响应头,凡带有rel=preload的资源都会被推送。如果应用输出的Link头包含大量资源,一个足够大的日记容量就显得尤为重要,否则哈希冲突会造成部分资源推送失效。
常见问题排查与最佳实践
第一个常见问题是“为什么浏览器缓存了资源还重复推送”。这通常是因为客户端没有回传推送日记。早期浏览器对推送日记的支持并不完整,Chrome在很长时间内不发送摘要信息,导致去重只能依赖单连接日记。排查时可以用curl的HTTP/2支持测试:
# 使用curl测试推送行为,观察PUSH_PROMISE帧 curl -sI --http2 -H "Accept: */*" https://www.ipipp.com/ -v 2>&1 | grep -i push
第二个常见问题是推送资源过多导致首字节时间变长。Server Push的本质是占用带宽优先级,推送十几个大文件会挤占HTML本身的传输。最佳实践是只推送渲染首屏必需的小体积资源,例如关键的CSS文件和字体文件,控制在3到5个以内,同时严格限制推送资源的体积。
最后必须强调版本兼容问题。由于Chrome 106之后移除了Server Push支持,HTTP/2 Push在实践中已经被103 Early Hints和preconnect等方案取代。如果你的Nginx版本高于1.25.1,http2_push_diary、http2_push等指令已被标记为废弃,建议直接迁移到Early Hints方案:add_header Link "</style.css>; rel=preload; as=style" 103;配合early_hints on;指令使用,能获得类似的预加载收益且兼容性更好。
总结一下,http2_push_diary的值决定了推送去重位图的容量,默认256满足绝大多数场景,取值必须是2的幂次方,且只在单连接内生效。理解它的位图原理和浏览器交互机制,才能在旧版本Nginx上稳定地使用Server Push优化页面加载性能。
Nginxhttp2_push_diaryHTTP/2 Server Push修改时间:2026-09-02 06:12:27