浏览器明明支持推送,服务端也开了推送,可资源还是等到页面加载完才姗姗来迟——这类现象在走代理IP 之后特别常见。问题往往不是服务端没推,而是推送在链路中途就断了,浏览器根本没收到。
服务器推送想省掉的那次往返
HTTP/2 的服务器推送,是服务端在返回主文档的同时,把接下来会用到的资源主动”塞”给浏览器:样式表、脚本、图片,趁浏览器还没开始请求就先送过去。省掉的是一来一回的往返时间,页面首屏往往因此快上一截。
推送的实现和普通响应不一样。服务端在同一个连接上开一条推送流,先发一个 PUSH_PROMISE 预告,再发真正的资源数据;浏览器收到预告后,可以决定接受还是拒绝,接受了就把它当成缓存里的资源用。
也就是说,推送能不能起作用,取决于两个前提:预告能到达浏览器,推送流能完整送达。这两步只要有一处被中间层处理掉,推送就白做了。
走代理IP 时链路多了一段转发,恰好是这类”看不见的处理”高发的位置。下面三个环节,是排查时最常发现问题的三处。
代理IP 链路上最常见的三种表现
预告被丢弃。部分中间层只转发常规的请求与响应,对推送流这类”服务端主动发起”的流量没有处理逻辑,直接忽略。表现是浏览器网络面板里没有任何推送痕迹,资源全在页面解析后才请求。
推送流被当成普通响应缓存。另一些中间层有缓存逻辑,把推送来的资源当普通响应处理,但推送流的头部和普通响应并不一样,缓存规则可能错配,导致资源要么不生效要么被错误地复用。
连接复用把推送冲散。代理IP 出口与浏览器之间如果有连接复用机制,推送流可能被拆分到错误的连接上,浏览器收到的预告和资源对不上号,最终放弃。
怎么判断推送到底生效没有
看网络面板。打开开发者工具,看主文档请求有没有关联的推送条目。有,说明推送链路是通的;完全没有,基本可以认定预告没到达。
对比直连与走代理IP。同一个地址,关掉代理IP 测一次,看资源是否提前到达;再走代理IP 测一次。两次结果不同,问题就锁定在转发这一段。
确认服务端确实开了推送。有的站点本身就没启用推送,别把没有推送当成链路问题。先用直连确认基线,再谈链路。
推送的资源确实用得上。推送也不是越多越好,推了一堆用不上的资源,反而挤占带宽。判断是否生效,要连”推送的资源有没有被用到”一起看。
自己搭站时能主动控制的就多一点:确认中间层对 HTTP/2 推送流的处理策略、别在代理IP 出口这一层开可能改写流的缓冲、把推送清单限定在首屏真正要用的资源上。
访问别人站点时能做的有限,主要是判断链路是否透传,以及把结论反馈给代理IP 服务的提供方。这项优化是锦上添花:有,首屏快一点;没有,也不影响正常浏览,排查时排在连通性和出口地区之后。
