HTTP/2协议带来的多路复用已经大幅提升了页面加载效率,但浏览器仍需等HTML解析完成后才知道要去请求哪些静态资源。HTTP/2 Server Push正是为了解决这个时序问题而设计,Nginx在1.13.9版本之后加入了原生的ngx_http_v2_module推送支持,只需简单配置即可将关键CSS或字体文件提前推送给客户端。另一方面,推送效果如何、Nginx本身运行状态如何,需要一套可量化的监控体系,KairosDB作为基于Cassandra的时序数据库,非常适合承接这类高频写入的指标数据。本文将两部分串联起来,给出一个性能优化加监控闭环的完整实践。

一、Nginx中配置HTTP/2 Push的完整方法
首先确认Nginx版本不低于1.13.9,并且编译时包含了ngx_http_v2_module模块,绝大多数发行版自带的Nginx都满足条件。接下来在监听端口上启用HTTP/2协议,然后使用http2_push指令指定要推送的资源路径。
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 /data/www;
# 静态推送:所有请求都推送首页样式
http2_push /css/main.css;
location / {
index index.html;
}
}上面的方式属于无条件推送,无论用户访问哪个页面都会推送同一份CSS,这显然不够灵活。更推荐使用http2_push_preload指令配合Link响应头,由后端应用决定推送哪些资源,Nginx只负责识别Link头并执行推送动作,这样控制权交给了业务层。
location / {
http2_push_preload on;
proxy_pass http://127.0.0.1:8080;
}后端应用只需在响应头中加上Link: </css/app.css>; as=style; rel=preload这样的声明,Nginx就会自动将该资源推送到客户端。需要注意推送的资源必须是同源的GET请求,跨域资源无法推送。另外,推送的数量要克制,推送浏览器已经缓存过的文件只会浪费带宽,部分现代浏览器对推送的支持也在弱化,因此上线前务必通过Chrome DevTools的Network面板观察推送是否生效,以及实际命中率。
二、推送日志与访问日志的结构化改造
要评估推送效果,必须先让日志变得可分析。Nginx默认的combined日志是纯文本,直接解析成本高。可以自定义log_format,把请求耗时、推送状态、连接的HTTP协议版本等字段以JSON格式输出,方便后续的日志采集器消费。
log_format json_analytics escape=json
'{'
'"time":"$time_iso8601",'
'"remote_addr":"$remote_addr",'
'"request_uri":"$uri",'
'"protocol":"$server_protocol",'
'"request_time":$request_time,'
'"bytes_sent":$bytes_sent,'
'"status":$status'
'}';
access_log /var/log/nginx/access.json json_analytics;拿到结构化日志后,可以用Fluent Bit或Filebeat采集,再经过一个转换脚本将关键指标写入KairosDB。例如每分钟聚合一次平均请求耗时、推送请求数、HTTP/2连接占比等指标,这些数据正是判断推送是否带来收益的直接依据。如果发现推送后首屏时间没有下降,常见原因包括浏览器缓存命中导致拒收、推送的资源体积过大占用了连接窗口,或者客户端根本协商的是HTTP/1.1。
三、将指标写入KairosDB并完成可视化
KairosDB提供REST接口,写入数据的核心是metric名称、时间戳、值和标签。假设我们已经聚合出了每分钟的平均请求耗时,就可以构造如下JSON提交到KairosDB的/api/v1/datapoints端点。
import requests
import time
url = "http://127.0.0.1:8080/api/v1/datapoints"
payload = [
{
"name": "nginx.request_time.avg",
"timestamp": int(time.time()),
"value": 0.128,
"tags": {"host": "web01", "scheme": "http2"}
}
]
resp = requests.post(url, json=payload)
print(resp.status_code)标签的设计很关键,KairosDB的查询过滤完全依赖tags,建议将主机名、协议版本、站点标识都作为标签写入,这样后续可以按任意维度做对比查询。写入频率控制在分钟级即可,HTTP/2推送这类优化指标不需要秒级精度,过高的写入频率反而会放大Cassandra的存储压力。
数据落库之后,在Grafana中添加KairosDB数据源,即可绘制请求耗时趋势图、推送命中率曲线等面板。一个实用的做法是把启用推送前后的数据放在同一时间轴上对比,用标签区分策略版本,收益一目了然。查询时KairosDB支持downsampling聚合,长期数据可以降采样保存,兼顾查询性能与存储成本。
最后补充一点经验:HTTP/2 Push并非银弹,若站点静态资源已经通过强缓存和CDN覆盖,推送的边际收益可能很小。正确的方式是持续依赖KairosDB中的监控数据做决策,推送、预加载、资源内联等手段都应该由真实数据来验证效果,形成配置、观测、调整的闭环,这才是这套架构真正的价值所在。
NginxKairosDBhttp2 push修改时间:2026-09-07 17:30:41