逐暗者的麦田 一位Java攻城狮的个人博客,主要分享编程、建站、动漫、趣闻和生活内容
博主 逐暗者的麦田

本站由 又拍云又拍云提供CDN加速/云存储服务

萌ICP备20237379号沪ICP备:13037081号-2,13037081号-1,13037081号-3 博主 昨天 22:48 在线自豪地使用 Typecho 建站搭配使用 🌻Sunny 主题当前在线 3 人
歌曲封面 未知作品

本站由 又拍云又拍云提供CDN加速/云存储服务

萌ICP备20237379号

沪ICP备:13037081号-2,13037081号-1,13037081号-3

网站已运行 3 年 58 天 9 小时 20 分

Powered by Typecho & Sunny

3 online · 32 ms

Title

优化博客首页访问速度

逐暗者

·

随笔

·

Article
⚠️ 本文最后更新于2023年08月19日,已经过了430天没有更新,若内容或图片失效,请留言反馈

背景

最近更换了博客程序和主题,网站首页访问比较慢。由于之前采用的是hexo生成的纯静态页面,所以觉得换成typecho驱动的博客,有点慢也是正常的。
等到把博客的内容都迁移完之后,就开始一点一点排查网站打开慢的原因了。

优化

cdn

打开一个网站比较慢,首先想到的是加载了很多内容,例如js、css、图片、字体文件等等。由于这些很少会发生变化,所以可以直接采用CDN的方式来加快速度。
好在主题提供了相关资源cdn的设置,又有又拍云免费的cdn,所以处理起来也是比较简单的。

除了配置cdn之外,可以在cdn的浏览器缓存中也设置一下,毕竟这些静态文件很有可能几周甚至几个月都不会更新。

静态缓存

对于博客来说,页面可以大致分为2种。一种是用户未登录,看到的都是一样的前端页面,这种非常时候缓存起来,下次再访问就不用再执行php和数据库查询了。
好在,宝塔面板也提供了这样的功能“宝塔网站加速”。

宝塔网站加速中可以配置typecho加速规则,几乎是一键设置了。这边我设置了8小时的缓存时间,这样8小时内未登录的用户访问同一个页面是非常快的。

可以看到,效果很明显,原本首页(TTFB)需要700毫秒的,现在只需要34毫秒。

排查TTFB耗时过长的问题

最后就剩下登录用户的访问和未登录用户首次访问的问题了。首页的TTFB有700毫秒,这个时间还是不太正常的。

排查数据库

看了一下数据库,博客的数据并不多,整库只有1M大小,博客数量低于一百,感觉不太可能是数据库慢了。当然为了以防万一,检查了一下数据库状态。

唯一有点问题的是创建临时表,有很大比例创建到了磁盘。查了mysql的文档,发现tmp_table_size这个配置并不能完全控制临时表的创建,例如表中存在text或者blob类型字段时,会被mysql写入磁盘的。对照的看了一下typecho的表结构,发现博客文章就是text类型,所以这个优化不了了。
除此之外,很容易想到有慢查询。查看慢查询日志没有结果。根据数据库数据量,都很难想象有慢sql。

排查php脚本

数据库方面暂时放下,于是想到了php是解释执行,会不会是php执行比较慢?
于是安装了opcache扩展,用于加速php的执行,结果TTFB并没有显著变化。

那会不会是php在创建数据库链接的时候比较耗时呢?于是使用了长链接

♾️ php 代码:
// 建立长连接
$conn = new PDO("mysql:host=$host;dbname=$db;charset=utf8", $user, $password, array(PDO::ATTR_PERSISTENT => true));

但也不明显,从数据库状态可以看到数据库链接在php执行结束后并没有释放,但是依旧没有减少TTFB。

最后只能开始排查php了,由于不是很会php的调试,只能在输出中打印代码耗时。

♾️ php 代码:
function qidiziTime($out = 0, $end =0) {
    if (!defined('qidiziTimeOn')) return;
    static $str = array();
    static $mt = null;
    static $init = null;
    if (null === $mt) $init = $mt = microtime(1);
    if ($end) {
        $str[] = 'all=' .round(microtime(1) - $init, 4);
        echo "<!--\n". implode("\n", $str) ."\n-->";
    } else {
        $t = microtime(1);
        $str[] = $out .' : '. round($t-$mt, 4) .' (' .$t. ')';
        $mt = $t;
    }
}

然后在index.php中一开始就执行

♾️ php 代码:
define('qidiziTimeOn',1);

再index.php的末尾执行

♾️ php 代码:
qidiziTime(0,1);

在主题的php文件中,不断插入

♾️ php 代码:
function_exists('qidiziTime') && qidiziTime(参数); 

通过对比不同打点时间来看是那段代码执行过长,然后再逐步缩小范围。最终发现php执行时间分布是这样的,第一部分typecho加载自身程序和插件,需要100毫秒左右。第二部分,主题查询各种文章、评论等信息,这些需要100毫秒左右。第三部分,有一个不是文章的div生成花了300多毫秒。
针对这个300毫秒进一步切分,发现时间几乎都是花在了2次调用外部请求(访问腾讯接口获取QQ用户名)。

如此一来,优化的方式也比较简单了,第一种方法干掉这个调用,暂时不需要QQ号查询用户名。第二种就是加一个redis缓存。

♾️ php 代码:
 function get_QqName($qq)
{
    $tool = $GLOBALS['tool'];
    $redis = $tool->getRedis();
    $res = $redis->get('sf_blog:qqname:'.$qq);
    if($res != null){
        if($res == 'sf_no_result'){
            return '';
        }
        return $res;
    }
    $res = //调用外部请求通过qq号获取qq
    if($res == null){
        $res = "sf_no_result";   
    }
    $redis->set('sf_blog:qqname:'.$qq, $res, ['nx', 'ex'=>604800]);
    return $res;
}

然后再试一下,TTFB的时间缩短到了200多毫秒。

现在已有 1014 次阅读,2 条评论,0 人点赞
Comment:共2条
发表
  1. 头像
    @
    要不你试试halo??
    · Windows · Chrome · 中国广东省广州市联通

    👍

    💖

    💯

    💦

    😄

    🪙

    👍 0 💖 0 💯 0 💦 0 😄 0 🪙 0
    1. 头像
      @
      halo的设计好奇怪,用的是key-value存储方式,不是很喜欢。
      · MacOS · Chrome · 中国上海市电信

      👍

      💖

      💯

      💦

      😄

      🪙

      👍 0 💖 0 💯 0 💦 0 😄 0 🪙 0
搜 索 消 息 足 迹
你还不曾留言过..
你还不曾留下足迹..
博主 不再显示
博主