刚迁移完网站,又发现了主页首字节响应时间过长的问题,个人站长真是注定折腾。

2017-02-27 更新

这一周网站有两个新变化,同时自己也收获到一个新的认识。

先说改变:第一个,网站启用了全站 HTTPS ,在使用 VeryCloud 的情况下,TTFB 又上涨了 100ms—200ms。

HTTPS 加密传输本来就会增加握手次数和 CPU 负担,我对这种牺牲提前做好了心理准备。

第二个,在浏览了大量前人经验和优秀网站后,我也意识到,即使启用 HTTPS 有所牺牲,也不至于使 TTFB 在 400ms+ 居高不下。

于是,我尝试切回了 360 网站卫士,不多说,效果见图:

那些为缩短 TTFB 做的努力(2017-02-27 更新)-极客飞船

感到欣喜,并表示:厉害,我的祎。

已换用腾讯云 CDN。发现接入 360 网站卫士后发现,搜狗浏览器和 360 的浏览器不响应 http 跳转 https 主页的请求,测试 Chrome、 Firefox 、Safari,正常;IOS 的 UC、猎豹,正常;直连或换用其它 CDN 也能消除问题。免费 CDN 真的不省心,还是万事加钱可及。

VeryCloud 出现过各种各样的性能问题,在四川电信尤其突出,但是用了这么久,若要一句话总结,“功过一半”吧。

再说说重要的新认识,和网站加载速度息息相关,也包括了 TTFB 。

我认识到,目前,网站的「动静分离」是不科学的,在 48个 网站首页总请求数中,有 41 个会被浏览器认为是来自本站,即使图片大部分是从七牛云加载。

问题来源于,七牛云的「自定义域名」被设置成了 cdn.geekufo.com 这样一个本站的二级域名,通过浏览器开发者工具可以观察到,无论是来自裸域(不带 www )还是 cdn.geekufo.com 的资源,都被赋予了同样的 Cookie。

假设每个 Cookie 大小为 1 KB,网站主页有 50 个来自本站的资源,那么就会产生 50 KB 的 Cookie 发送,上行带宽越低就越耗费时间,而极大数量的静态资源其 Cookie 是没有必要发送的。同时,还忽略了浏览器对单位域名的并发限制,虽然现代浏览器有了提升,但较高的也只有 10 (Win10 Edge),Chrome、 Firefox 等其他产品大多为 6 或 8。

所以仔细观察的话,我们能发现,即使是大型网站,例如淘宝,它的资源也链接到了 img.alicdn.com、 log.mmstat.com、 ecpm.tanx.com 等 10 多个域名,这样就又知晓了一个让网站更 Professional 的必要工作。

那些为缩短 TTFB 做的努力(2017-02-27 更新)-极客飞船

概述

TTFB(Time To First Byte),是指:从客户端发起网络请求至收到服务器返回的第一个字节中间这段时间。

当你看到一个网站的标签旋转了半天才有内容逐渐显示,可能不是因为设备或网速不行,而是该页面的 TTFB 过长。

想象一下:如果连续浏览 10 个网页,前面 9 个都能在半秒内出现内容,而第 10 个却需要等待 2 秒后才开始加载,那么人就会感到明显的钝斥感。

事实上一个叫 Nielsen 的团队做过一项调查,结果显示任何超过 100 毫秒的响应都会让用户感到他们在等待。

这是非常不好的体验,尤其是对于初次到访的用户,容易留下负面的第一印象。

所以在互联网产品人的工作手册中,有个词叫做「心流」,我自己的解释是:身心完全投入当下行为以满足某种期望的专注。

「心流」很容易被打断,于是我们才看到越来越多的过渡动画被加入到 Web 、移动甚至桌面应用中,其作用就是为了分散用户在等待期间的注意力,即使实际加载速度可能并没有得到提升。

但这并不意味着实际加载速度不重要,无论是性能还是过渡都是为产品更好服务的,而 TTFB 就是关于性能的一项硬性指标。

思考成因

这次发现的首页 TTFB 在 1000ms 到 2000ms 徘徊,几乎没有 1000ms 以下的时候。

按照 Apdex 的标准,这个成绩接近“不可容忍”的水平,在目前的互联网大环境下,实际上已经是不能容忍。那些为缩短 TTFB 做的努力(2017-02-27 更新)-极客飞船
(腾讯优测给出的定义,TTFB 只是组成“白屏时间”的一部分)

但是造成 TTFB 过长的因素非常多,当时我能想到的有:

  • 服务器的硬件性能和资源占用;
  • 页面大小、复杂程度;
  • 环境配置的正确与否;
  • 源站代码;
  • DNS 解析的连通情况;
  • CDN 的性能;

不可避免的又要进行一场分析和试错。

做排除法

根据问题成因的大致轮廓,我也构思了一个粗略方案:

1. 先找到同是 WordPress 搭建,并且服务器规格、首页大小和复杂程度相似的站点对比;

2. 找到使用同样 WordPress 主题的站点,确认是否是 timthumb.php 的通病;

3. 用 17ce 的 DNS 检测工具确认 DNS 连通情况;

4. 切换到其他 CDN 对比 TTFB 变化。

执行情况

第一站找到了张戈的博客,我记得张戈有说过自己也用的超低配服务器。

其他方面是种直觉吧,根据图片清晰程度,页面压缩率,插件的相似性等等。当时也不知道对不对,结果证明了他的博客主页「请求总次数」和「文件总大小」和极客飞船非常接近。

那些为缩短 TTFB 做的努力(2017-02-27 更新)-极客飞船

但张戈博客首页的 TTFB 只有两位数毫秒,而且张戈博客的 PV 比我这小站高得多,这也证明了:服务器配置低不是问题所在

那些为缩短 TTFB 做的努力(2017-02-27 更新)-极客飞船

接下来,我找到了续笔记和安全者两个站点,它们和极客飞船用的同一主题,并且缩略图都通过 timthumb.php 动态生成。我还发现,这两个站点并没有把 PHP 设置成 expose_php = Off,所以通过响应头可以获知其 PHP 版本。

那些为缩短 TTFB 做的努力(2017-02-27 更新)-极客飞船

这样进行对比,就能大概地分析出主题、 timthumb.php 、lazyload 以及 PHP 版本 对 TTFB 的影响。

首先是 PHP,极客飞船的 PHP 大版本和二者一样,所以 PHP 版本的因素应该能排除

为了尽可能地和两站一致,我也开启了 lazyload,TTFB 无明显变化,lazyload 被排除

然后判断是否和 timthumb.php 的动态缩略图生成有关。这两个站点的 TTFB 在 100ms – 500ms 之间,虽然不算慢,但包括极客飞船的在内都不如张戈博客,同时 TTFB 的变化范围也比较大,而张戈博客并没有使用 timthumb.php。

于是禁用 timthumb 缩略图,从实际效果看来,TTFB 没有明显变化,并且总的加载时间也没有想象中那样减少,timthumb.php 排除

继续通过 17ce 检测全国 DNS 解析情况,由于我是通过四川电信访问网站时发现的 TTFB 问题,所以包括下面的 CDN 项检查,也优先关注在四川的各项网络性能。

检测显示,四川电信的 DNS 解析时间用时 60ms 左右,即使没有这个 DNS 解析用时,TTFB 也依然不低。所以,不是 DNS 的问题

那些为缩短 TTFB 做的努力(2017-02-27 更新)-极客飞船
那么就只剩下 CDN 了。

没有完美又免费的午餐

极客飞船之前在文章 「网站CDN搭建方法和缓存策略分享」中对比过目前市面上主流的免费 CDN,并最终选择了VeryCloud,理由除了文中提到的缓存策略和 HTTPS 支持,这里还要补充的是拥有参数过滤和移动端 APP。

从功能的丰富程度上来看,结合网站的流量消耗, VeryCloud 近乎完美,全面满足了我的需求。但也要承认,当初在选择和搭建 CDN 时并没有太多地关注 TTFB 这项指标,那时看到网站从 8 秒的加载时间缩短到 3 秒内已感到十分满足。

所以,为了确定问题所在,必须再次比较各个 CDN,并且还要检查 CDN 是否只在四川分发节点存在问题。

仍然借由 17ce 测试,报告会输出全国各地在不同运营商网络下访问首页的 TTFB。

测试结果惊人:

1. 当使用电信访问时,包括四川在内的个别地区出现了明显“偏科”,TTFB 大不如其他地区;

2. 同样是使用电信的前提,轮流测试各个 CDN,对比后发现:VeryCloud 的 TTFB 是最长的。

当时的数据忘记了截图,只能用文字描述下:“偏科”的 TTFB 在 1000ms +,大概有 4、5 个省市如此,而其他地区都多在两位数毫秒级,高一点的不超过 200ms。

最终确定,问题主要出在 CDN 上

再进一步

难到只能换 CDN 了?或是“万事加钱可及”?

众所周知即不花钱又要好用的 CDN 是稀缺资源,如果 CDN 的性能堪忧,就是外部条件受到了限制,别人家的问题你要怎么解决?

但是不甘心呐,最后还是让我发现了 VeryCloud 的小“秘密”。

那些为缩短 TTFB 做的努力(2017-02-27 更新)-极客飞船

与其他 CDN 相比,VeryCloud 在接入时有个不同,就是上图中的「探测 URL」,这里要求填写站点任意一个资源的 URL,例如 http://geekufo.com/demo.html我的推测是用于检测网站的连通性。

一直以来我都是通过一张 GIF 图探测,大小约为 5KB。那么就有可能是这张图片太大,影响了检测效率,抱着试一试的心态,我重新上传了份只有 1 字节 的文本用于探测。

重填「探测 URL」后,奇迹出现了,再次测试 TTFB 缩短到了 500ms 和 1100ms 之间。

成绩有了大幅提升,只是还不够优秀,不够稳定。

最后一点折腾和感悟

极客飞船最终还是把 TTFB 缩短到了 200ms 以内。

那些为缩短 TTFB 做的努力(2017-02-27 更新)-极客飞船

有的时候就是不到黄河不死心,谁也不知道会不会柳暗花明又一村。

上面的过程恰逢网站搬完家,所有的软件配置还是沿用了搬家前的“老一套”,包括老旧的 PHP 5.x 。

然而已经有非常多的测试证实了 PHP 7.x 的性能是 PHP 5.x 数倍。

没错,最后我选择了再次重装,直接把 PHP 升级到了 7+,顺带还升级了 Mysql、Apache 。

此外,Wp Super Cache 也被我当成了最后的救命稻草,在其设置中勾选上了「首页额外检查」以及取消勾选「不要为已知用户缓存」

在无意中,我发现了一个现象,大家可以做下实验:

勾选「不要为已知用户缓存」,并当处于登录状态时,首页的 TTFB 要比不勾选多出一倍。

那些为缩短 TTFB 做的努力(2017-02-27 更新)-极客飞船

像本站不勾选时 TTFB 就稳定在 100ms-200ms,勾选上就会增加到 400 ms+。

其实进行到这,TTFB 就达到理想水平了。只是我还是有些懵圈,无法确定是自己做的这些工作起了关键作用,还是 CDN 那边一时的性能问题。

但至少还是可以总结出一些姑且能被称作“技巧”的经验:

1. 用 VeryCloud 时,「探测 URL」对应的资源越简单越好;

2.PHP 7+ 一定是更先进的,但从 PHP 5.x 升级到 PHP 7.x 并不能盲目,由于函数的一些变化,可能造成 WordPress 主题不兼容,具体可以参考官方文档:从PHP 5.6.x 移植到 PHP 7.0.x 

3.调试 WP Super Cache 时可以尝试先围绕「任何情况下都调用缓存」来设置,并启用「预缓存」。Nginx 是怎样的我不了解,但我感觉 Apache 下合理地配置 WP Super Cache 对优化 TTFB 能起到很大作用。

这篇文章没有分享什么“万金油式”的方法,原因一个是影响 TTFB 因素的确实太多了,二来不同站点间的情况也各有差异。

就这样,把自己折腾的过程记录下来,希望对亟需解决同样问题的朋友能起到帮助。