$server_protocol 是 Nginx 记录实际协商 HTTP 协议版本的内置变量,是监控协议演进最直接、可靠、零侵入的数据源,需在日志中结构化采集并结合 TLS、UA 等变量交叉分析以驱动渐进式升级。

$server_protocol 是 Nginx 内置变量,其值形如 HTTP/1.1 或 HTTP/2.0(实际为 HTTP/2),记录当前请求所使用的 HTTP 协议版本。它不反映客户端“支持什么”,而反映“本次连接实际协商并使用的协议”。因此,它是监控站点真实 HTTP 版本演进的**直接、可靠、零侵入**的数据源。
采集:在日志中结构化记录协议版本
在 Nginx 配置的 log_format 中显式加入 $server_protocol,确保每条访问日志都携带该字段:
log_format http_proto '$remote_addr - $remote_user [$time_local] '
'"$request" $status $body_bytes_sent '
'"$http_referer" "$http_user_agent" '
'$server_protocol;重启 Nginx 后,日志中将出现类似:
192.168.1.100 - - [10/Jul/2024:14:22:35 +0800] "GET /index.html HTTP/1.1" 200 1234 "https://example.com/" "Mozilla/5.0..." HTTP/1.1;
注意:$server_protocol 值不含斜杠转义(如 HTTP/2 而非 HTTP\/2),便于后续解析。
分析:按时间维度聚合统计协议分布
使用日志分析工具(如 Logstash + Elasticsearch、GoAccess、或简单用 awk + sort)按小时/天提取协议占比:
- 提取当天所有协议出现次数:
awk '{print $13}' access.log | sort | uniq -c | sort -nr - 按小时统计 HTTP/2 占比(假设第4字段是时间,第13字段是协议):
awk '{hour=substr($4,2,13); print hour,$13}' access.log | awk '{cnt[$1,$2]++; total[$1]++} END {for (i in cnt) {split(i,a,SUBSEP); printf "%s %s %.1f%%\n", a[1], a[2], cnt[i]/total[a[1]]*100}}' | sort
关键看趋势:HTTP/2 比例是否持续上升?HTTP/1.1 是否集中在特定旧设备 UA 或特定时间段(如爬虫高峰)?
关联:结合 TLS 和客户端特征交叉验证
仅看 $server_protocol 不足以定位瓶颈。需联动其他变量判断升级受阻原因:
-
是否因 TLS 不达标降级? 检查
$ssl_protocol(如TLSv1.2)和$ssl_cipher。若大量 HTTP/1.1 请求伴随TLSv1.0或弱密钥,说明客户端 TLS 能力不足,无法启用 HTTP/2 -
是否因浏览器老旧? 提取
$http_user_agent,匹配 IE11、Android 4.x WebView 等已知不支持 HTTP/2 的 UA -
是否因 CDN 或中间代理干扰? 若
$server_protocol为 HTTP/1.1,但$http_x_forwarded_for显示来自知名 CDN IP,需检查 CDN 是否终止了 HTTP/2 连接
行动:识别可优化的长尾流量并定向推动
当发现某类流量长期卡在 HTTP/1.1(如某款企业内网浏览器占比 3% 且稳定),可采取务实策略:
- 对这部分 UA 返回轻量级 HTML(禁用 JS/CSS 冗余资源),缓解 HTTP/1.1 多路复用缺失的影响
- 在响应头中添加
X-HTTP2-Advisory: upgrade-recommended,供前端 SDK 上报,辅助产品侧推动客户端升级 - 若该 UA 已无维护,可在 WAF 层设置规则,对高频低价值 HTTP/1.1 请求限速,释放服务器连接资源
监控目标不是 100% HTTP/2,而是让协议升级节奏与用户真实环境演进保持同步——$server_protocol 正是这个节奏最诚实的节拍器。

















