导读:本期聚焦于小团团创作的《如何正确配置Nginx的http2_push_diary_max_entries最大条目数?》,敬请观看详情。如果Nginx在单个HTTP/2连接上持续推送静态资源,却没有一个容量上限来约束推送记录,内存会怎样变化?http2_push_diary_max_entries就是用来给每个连接中的推送日记设定最大条目数的指令。它属于Nginx HTTP/2模块较新提供的细粒度控制项,默认值通常为256,配置位置可以是http或server级。这个数值决定了Nginx在内存中能记住多少条已经发起的推送记录;一旦记录达到上限,继续产生的推送信息将按内部策略处理,可能停止新增推送或覆盖旧记录。理解这个上限需要结合http2_push_preload、http2_max_concurrent_pushes等指令一起看,否则很容易把并发推送数量限制和日记条目上限混为一谈。本文会从配置语法、运行机制和调优案例三个角度拆解该参数,说明怎样根据页面资源数量选择合理的值,并避开配置后不生效、内存占用异常等常见问题。

HTTP/2 Server Push允许服务器在客户端请求HTML之后,主动把CSS、JavaScript、字体等关联资源推送到连接中,从而省去浏览器解析后再发起的多次请求。然而,Nginx在记录这些推送动作时需要一个类似日记的结构,http2_push_diary_max_entries正是控制该结构容量的关键参数。

如何正确配置Nginx的http2_push_diary_max_entries最大条目数?

指令定位:日记最大条目不是并发推送数

很多配置Nginx HTTP/2推送失败的情况,都是因为把几个看起来相似的参数混在了一起。http2_push_diary_max_entries控制的是推送日记的容量,也就是Nginx为每个HTTP/2连接准备的一块记录区域中,最多能保存多少条已经推送过的资源信息。它并不直接决定同一时刻可以并行推送多少个资源。真正限制单连接并发推送数量的是http2_max_concurrent_pushes,默认值通常为10。前者像一个已经发送清单的容量,后者则像同时发送的通道数量。

推送日记存在的意义,是防止同一个资源在同一个连接上被重复推送。例如浏览器已经收到了style.css,但后续某个请求又触发了对style.css的推送判断,Nginx可以通过日记里保存的记录识别出该资源已经推送过,从而跳过重复推送。日记条目越多,Nginx能够记住的资源就越多,重复推送的概率就越低;但相应地,每个连接占用的内存也会增加。因此这个参数本质上是一个内存与推送准确率的平衡点。

一个常见的误区是:把http2_push_diary_max_entries调得很大,期望提高HTTP/2并发推送能力。实际上如果并发推送数量没有被放宽,仅增大日记条目数并不会让更多资源同时推送。它只会让Nginx记住更长时间的推送历史。要扩大并发推送能力,需要同时调整http2_max_concurrent_pushes。

http {
    http2_max_concurrent_pushes 20;
    http2_push_diary_max_entries 512;

    server {
        listen 443 ssl http2;
        server_name ipipp.com;
        ssl_certificate     /etc/nginx/ssl/ipipp.com.crt;
        ssl_certificate_key /etc/nginx/ssl/ipipp.com.key;

        location / {
            http2_push /css/style.css;
            http2_push /js/app.js;
        }
    }
}

配置方式与参数说明

该指令的语法非常简洁,通常出现在http或server级别的配置块中。默认值一般是256,这意味着每个HTTP/2连接默认有256条推送记录空间。对于大多数中小型网站来说,这个默认值已经足够。但如果一个页面会触发五六十个以上的资源推送,并且用户在一个连接上停留时间较长,就可以考虑把该值调高。

配置时需要注意,0是一个特殊值。将http2_push_diary_max_entries设为0,通常表示不保留推送日记。这样一来,Nginx将无法通过日记识别已经推送过的资源,重复推送的概率可能明显上升。因此除非有极特殊的内存限制需求,否则不建议把这个参数直接设为0。合理范围通常可以设在256到2048之间,具体数值需要根据页面平均资源数量以及单连接生命周期的访问深度来决定。

还需要补充的是,这个参数仅有容量限制意义,并不会自动开启HTTP/2推送。要真正触发Server Push,仍然需要配合http2_push指令或http2_push_preload指令。如果只设置了最大条目数,而没有配置任何推送规则,那么这个参数实际上不会产生可观察的效果。

http {
    http2_push_preload on;
    http2_push_diary_max_entries 1024;
    http2_push_diary_pipe_size 1m;

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

        location / {
            add_header Link "<style.css>; rel=preload; as=style";
            add_header Link "<app.js>; rel=preload; as=script";
        }
    }
}

运行机制:什么时候会达到最大条目

当Nginx通过Link响应头或http2_push指令识别到一个可以推送的资源时,它会先检查该资源是否已经被记录在推送日记中。如果没有记录,并且当前并发推送数没有超过http2_max_concurrent_pushes的限制,Nginx就会发起推送,同时把这条推送信息写入日记。这个写入过程会让日记条目数逐渐增长。随着连接上的请求越来越多,日记中的条目会不断累积,直到达到http2_push_diary_max_entries设定的上限。

达到上限之后,Nginx通常需要为新条目腾出空间。不同的内部实现策略可能有所不同,但可以理解为较旧的记录会被淘汰。也就是说,最早推送过的资源信息会被移出日记。如果之后再次遇到对这些旧资源的推送判断,Nginx可能会认为它们没有被推送过,从而再次推送。对于资源数量非常多、连接生命周期非常长的场景,这种重复推送会浪费一部分带宽。因此设置上限时要考虑一个典型连接生命周期内可能涉及多少资源。

从实际观察看,如果单个页面资源数量在50个以内,默认的256条通常足够。若页面包含数百个子资源,并且用户会在当前页面停留较长时间,再配合其他脚本持续发起请求,那么旧记录被淘汰的概率就会升高。此时可以尝试把值调高到512、1024甚至更高,同时观察RTT和带宽变化。

curl -I -k https://ipipp.com/style.css
# 观察响应头中是否包含 Link 字段
# 如果存在类似 Link: <app.js>; rel=preload; as=script,表示该资源触发了推送判断

调优建议与常见故障排查

调整http2_push_diary_max_entries之前,建议先统计单个页面实际需要推送的资源数量。可以通过浏览器开发者工具查看网络面板中的推送资源数量,也可以在Nginx访问日志中增加相关字段。如果发现资源数量远大于默认的256,并且用户在一个连接上会访问多个页面,那么提高该值是合理的。提高后可以使用nginx -t检查配置语法,再用nginx -s reload平滑生效。

如果配置后没有看到任何推送资源,需要先排查前置条件。第一是监听端口是否启用了http2参数;第二是http2_push_preload是否开启,或者是否使用了http2_push指令显式指定资源;第三是TLS证书是否有效,因为HTTP/2 Server Push在明文h2c环境中通常不受支持。若前置条件都满足,仍然没有推送,则要检查响应头中的Link字段是否被其他add_header或代理层覆盖。

还有一种常见问题是:配置了很大的http2_push_diary_max_entries,却发现内存占用上升明显。每个连接的日记都会占用一定内存,连接数较多时影响会被放大。此时应先观察活跃连接数,再决定是否需要按server级别对不同站点单独设置,而不是在http级别统一设置一个很大的值。对于静态资源数量不多、连接生命周期较短的站点,保持默认值反而是更稳妥的选择。

http {
    http2_push_preload on;
    http2_max_concurrent_pushes 16;
    http2_push_diary_max_entries 768;

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

        location / {
            http2_push /assets/main.css;
            http2_push /assets/main.js;
        }
    }
}

与http2_push_preload和http2_max_concurrent_pushes的关系

http2_push_preload用于自动读取响应头中的Link preload信息。开启后,只要上游应用或Nginx自身通过add_header输出了符合规范的Link响应头,Nginx就会尝试发起Server Push。它和http2_push_diary_max_entries是配合关系:前者决定是否产生推送行为,后者决定推送行为的历史记录能留存多少。

http2_max_concurrent_pushes则是更直接的限制条件。它规定了单个HTTP/2连接上同时允许的推送数量。如果该值为10,那么即使日记条目有1000条,同一时间也只能推送10个资源。反过来,如果并发推送数设置得很大,但日记容量很小,那么早期推送记录会被迅速覆盖,可能带来重复推送问题。因此这三个参数最好放在一起评估,而不是孤立修改某一个。

综合来看,中小站点可以保持http2_push_diary_max_entries默认值,只关注http2_push_preload和http2_max_concurrent_pushes即可。大型单页应用、拥有大量字体和图片资源的站点,则可以把日记条目数适当调高,同时观察带宽和内存变化,找到适合自己的平衡区间。

Nginx HTTP/2 Server Pushhttp2_push_diary_max_entries推送日记最大条目修改时间:2026-08-25 12:29:52

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