网站LOGO
逐暗者的麦田
页面加载中
7月22日
网站LOGO 逐暗者的麦田
一个java软件攻城狮
菜单
  • 热评
    用户的头像
    首次访问
    上次留言
    累计留言
    我的等级
    我的角色
    打赏二维码
    打赏博主
    优化博客首页访问速度
    点击复制本页信息
    微信扫一扫
    文章二维码
    文章图片 文章标题
    创建时间
  • 一 言
    确认删除此评论么? 确认
  • 本弹窗介绍内容来自,本网站不对其中内容负责。
    • 复制图片
    • 复制图片地址
    • 百度识图
    按住ctrl可打开默认菜单

    优化博客首页访问速度

    shellingford · 原创 ·
    随笔 · 网站调优
    共 3176 字 · 约 3 分钟 · 828
    本文最后更新于2023年08月19日,已经过了338天没有更新,若内容或图片失效,请留言反馈

    背景

    最近更换了博客程序和主题,网站首页访问比较慢。由于之前采用的是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多毫秒。

    声明:本文由 shellingford(博主)原创,依据 CC-BY-NC-SA 4.0 许可协议 授权,转载请注明出处。

    还没有人喜爱这篇文章呢

    现在已有

    2

    条评论
    我要发表评论
    1. 头像
      执念
      • 等级:Lv.2
      • 角色:访客
      • 在线:很久之前

      要不你试试halo??

      · · · 广东-广州
      1. 头像
        shellingford 执念

        halo的设计好奇怪,用的是key-value存储方式,不是很喜欢。

        · · · 上海-上海
    博客logo 逐暗者的麦田 一个java软件攻城狮
    MOEICP 萌ICP备20237379号 ICP 沪ICP备13037081号-2,沪ICP备13037081号-1,沪ICP备13037081号-3 又拍云 本站由又拍云提供CDN加速/云存储服务

    💻️ shellingford 7月14日 在线

    🕛

    本站已运行 2 年 331 天 7 小时 21 分

    🌳

    自豪地使用 Typecho 建站,并搭配 MyLife 主题
    逐暗者的麦田. © 2021 ~ 2024.
    网站logo

    逐暗者的麦田 一个java软件攻城狮