国外网站速度慢,是为什么 / 随笔谈

可能你心中会直接给出一个答案。不,不提那个,我想从原理上说起。

十年前跟现在的网络慢,原因并不同

还记得十年前,我一不小心打开了 Facebook,虽然能打开,但速度极慢。

那个时候的网页都很单纯,也并不大。此时速度慢只能归结于:这是一个远在美国的网站,所有的访问需要经过海底光缆,刚好那个时候国际网络比较慢咯。

十年过去了,互联网产业也有了很多的变化。其中很重要的是,CDN 越来越普遍。很多网站用上它之后,服务器跟客户端的距离变近了。我们访问很多网站的时候,看起来是个在美国的公司,但实际上连接的却是在香港、台湾甚至境内的 CDN 服务器。现在,速度理应快了才对啊。

但为什么,越来越多的网站,打开的时候明明看到标题了,页面却要空白很久呢?除了网站离我们太远,还有别的原因。

我们先来看看一张网页的组成。

一张网页的加载流程

下图是 HTTP Archive 在 2017 年 3 月对世界上前 1000 热门网站的统计。平均每张网页会有多大呢?

先解释一下几个名词:

  • HTML:网页的基础,相当于房子的地基和砖块,通常会包含页面上的文字,并定义其它资源的地址;
  • 样式表:CSS,相当于图纸,定义网页的样式,比如你看到的文字的颜色、大小、排列、边框等等,都由它定义;
  • JS 程序:JavaScript,网页会“动”起来全是因为它,有能力改写整个网页;
  • 字体:指的是字体文件,中文网页嵌入字体并不多(因为中文字多,字体文件通常会太大);嵌入了字体之后,不用做图,即便浏览器上没装字体,也能显示嵌入的有“个性”的字体。

我们打开一个网页,载入的其实先是 HTML,然后 HTML 里面可以引用别的资源,比如样式表、JS 程序等等。这些资源可以在同一服务器,也可以在别的服务器(域名)上。

看图你就会发现,现在的网页,HTML 本身并不大,然而样式表和字体的平均大小却能和 HTML 相当,最夸张的是 JS,是 HTML 的 8 倍多。然而,如果没有样式表和 JS,我们看到的网页就没有现在这么好看、好用了。

我强调字体、样式表和 JS 程序,原因很简单。因为它们重要,所以浏览器载入网页的时候,会等它们加载完,才能显示。HTML 加载完了,还得等待样式表和 JS 程序全部下载完毕,否则浏览器就不知道页面究竟要怎么显示。

当然,如果边下载边显示,也不是不行。但这就需要不停地“重绘”页面,在屏幕上的表现就是画面不停地变化,看起来也不好看。所以有些浏览器会等到“必须”的、跟页面显示效果关系最密切的样式表和 JS 程序下载完才开始显示。这个策略,浏览器有专用的术语,叫“阻塞”。

而图片和视频并不会“阻塞”浏览器,浏览器下载的时候会做优化,会让他们延后再开始下载,所以它们虽然大小很大,但并不会影响页面“首次渲染”的时间。

为啥会慢?因为公用的资源

所以,网页加载速度缓慢,可能有下面这些原因。

  1. 下载 HTML 的速度慢,也就是连接源服务器的速度就慢,这个怨不了谁。
  2. HTML 全部下载下来了,但是 HTML 里引用的资源加载速度慢,所以 HTML 定义的标题显示出来了,内容却要空白很长时间。

你说那些浏览器的加载策略怎么这么笨,不优化一下呢?首先,大多数时候浏览器还是比较聪明的,有些资源会直接跳过,但有些浏览器认为很重要的资源是必须“阻塞”、不会跳过的,宁愿多等一会,比如样式表。你也不愿意看到下面这种没有样式表的画面吧……

模拟的样式表加载失败的效果

为什么我们在访问国外的网页时,这种情况会经常出现呢?因为国外的网页引用的资源,会经常引用一些不在自己服务器上的公用资源。比如:

  • Facebook 的点赞按钮的小程序;
  • CDN 上的 JS 程序库;
  • Google 托管的英文字体;
  • Google 的广告;
  • ……

为什么要用公用的资源呢?一个是方便,另一个则是省流量。假设 A、B 网页都引用了同一个点赞按钮的程序,你打开过 A 网页,点赞按钮的程序就下载了下来,以后你打开 B 网页的时候,因为这部分程序有缓存,所以就不用完整下载点赞按钮的程序了。

然而,只要这些资源下载失败,浏览器就会等待,直到“超时”,即便可能对你有用的 HTML 内容已经被下载到浏览器里了(这种时候你查看页面源代码,可能就已经能看到需要的信息了)。有时页面加载到一半然后卡住,也有可能是这种情况。

这个“超时”的时间是多少呢?就拿 Firefox 做例子,默认的时间从 90 秒到 300 秒不等。(下载到不同阶段,对应的超时时间也是不同的)不等完超时,页面就没法正常载入,所以,看起来就是等了十几秒,页面却一片空白,加载不出来了。

至于字体下载不下来,在有些浏览器上的效果很神奇:页面有些有字体的部分可以选中,可以复制,却什么字都看不到,一段时间之后,突然那些字的字体下载完毕,就漂漂亮亮地出现了。

这里提供一个小小的判断页面加载失败原因的方法:

在电脑浏览器上按 F12,会弹出一个只针对当前页面的调试工具。点开网络或者 Network,然后刷新页面,你就能看到每个资源的加载速度和结果了。比如在我这,jquery.min.js 是 pending 也就是等待的状态,再等一会就会变成红色的 failed(然而下图并不是 GIF),点开它们就能在右边看到具体的地址。

公用的资源为啥会慢?

最后你肯定想问,为什么那些公用的国外资源,访问就那么困难呢?简单说说原因吧:

  • Google、Facebook 等大部分的服务器并没有进驻中国大陆,所以在三四年前几乎无法访问。(不过 Google 这一两年给一些不是很敏感的公共服务在北京开了服务器,可能因为它是全球最大广告商吧)
  • 别的公用资源很多都被放在国外的 CDN 上,公用的资源有时候也会被一些反动网站利用,因此国家对反动网站采取措施的时候,免不了会误杀。这部分反而是现在主要会遇到的问题。
  • 近年来整个互联网已经进入了 HTTPS 的加密时代,进而这些公用的资源也开始了加密。对于加密的内容,传输阶段是无法读取具体访问的内容的,因而很多国外的 CDN 服务在看起来相似的加密连接下,有可能有正常请求,也有可能有反动请求。误杀的情况就更加不可避免了。

了解了原因,遇到慢到掉渣的国外网页,你还是只有两个简单而实际的方法:站起来走一圈,或者站起来跳出去。

参考文献:

发表评论

电子邮件地址不会被公开。 必填项已用*标注