网站性能优化实战:TTFB 从 1.71s 降到 0.38s

前言

最近对自己的博客做了一次全面的性能体检和优化。网站用的是 Typecho + Handsome 主题,在阿里云服务器上跑着 Nginx + PHP 7.4,配置其实不差(5.5G 内存、217G 硬盘、CPU 负载常年 0.2),但打开首页就是慢,TTFB 动不动 1.7 秒。

查了一下发现几个严重问题:OPcache 根本没启用、静态资源从百度 CDN 远程加载、Nginx 缓存策略也不完善。这次优化全程只改了配置,没动一行业务代码,效果立竿见影。


第一步:全面备份(保命要紧)

动配置前先把家底备份好:

# 数据库
mysqldump -u db_user -p db_name --complete-insert --routines > site_backup.sql

# 网站文件
tar czf site_files.tar.gz /www/wwwroot/example.com/

# Nginx 和 PHP 配置
cp /www/server/nginx/conf/nginx.conf ./
cp /www/server/php/74/etc/php.ini ./

数据库、文件、Nginx 配置、PHP 配置、主题 CDN 配置一个不落,服务器和本地各存一份,双重保险。


第二步:OPcache 启用——效果最爆炸的一步

这是整个优化中收益最大的改动。

问题

PHP 7.4 编译时带了 --enable-opcache,opcache.so 文件也存在,但 php.ini 里所有 opcache 配置全是注释状态。这意味着每次用户访问,PHP 都要重新解析编译所有脚本文件,完全没有脚本缓存。

这才是 TTFB 高达 1.71 秒的元凶。

解决

zend_extension=opcache.so
opcache.enable=1
opcache.memory_consumption=128
opcache.max_accelerated_files=4000
opcache.revalidate_freq=60
opcache.validate_timestamps=1

加了一行 zend_extension=opcache.so 把扩展加载进来,再把关键配置取消注释,重启 PHP-FPM 即可。

效果

启用后 TTFB 从 1.71s 降到 0.38s,降低了 78%。OPcache 让 PHP 脚本的编译结果缓存在共享内存中,后续请求直接执行缓存的 opcode,省掉了重复编译的开销。


第三步:静态文件本地化

问题

Handsome 主题的 CSS、JS 文件默认从百度 CDN(apps.bdimg.com)加载。虽然 CDN 本身速度不错,但对于国内服务器来说,多一次 DNS 解析和 HTTP 连接就是多几十毫秒延迟。而且万一 CDN 挂掉,网站样式都加载不出来。

解决

Handsome 主题早就内置了本地资源的副本,只是没启用。在后台配置中找到 CDN 公共库选项,从"百度 CDN"改为"本地"即可。

具体来说,这个配置存储在 Typecho 数据库的 typecho_options 表中,字段名 theme:handsome。配置值是一个序列化的 PHP 数组,其中 publicCDNSelcet 字段控制 CDN 选择:

  • 1 = 百度 CDN
  • 6 = 本地

用 MySQL 直接更新:

UPDATE typecho_options 
SET value = REPLACE(value, 's:15:"publicCDNSelcet";s:1:"1";', 
                          's:15:"publicCDNSelcet";s:1:"6";')
WHERE name = 'theme:handsome';

额外的:Local CDN 配置优化

Handsome 的 LOCAL_CDN 配置中,vditor 编辑器资源仍然指向 cdn.jsdelivr.net。既然要走本地化,顺手也把它改了。不过要注意,主题的 footer.php 会自动给 vditor 路径追加 /dist/method.min.js,所以配置值只需要填基础路径 vditor 即可。

{
  "vditor": "vditor"
}

结果

所有 bootstrap CSS/JS、jquery、mdui、vditor 等资源现在全部从自己的服务器加载,不再依赖外部 CDN。


第四步:Nginx 缓存策略优化

问题

虽然 Nginx 的 gzip 压缩已经开启(宝塔面板默认),但静态文件缓存策略不够完善:

  • 图片缓存 30 天,但没有 immutable 标记
  • JS/CSS 只缓存 12 小时
  • 字体文件(woff2、ttf、eot)完全没有缓存规则

修改

优化后的站点配置:

# 图片缓存 30 天
location ~ \.(gif|jpg|jpeg|png|bmp|swf)$ {
    expires      30d;
    add_header Cache-Control "public, immutable";
}

# 字体缓存 365 天(字体文件很少更新)
location ~ \.(woff2?|eot|ttf|otf)$ {
    expires      365d;
    add_header Cache-Control "public, immutable";
}

# JS/CSS 缓存 7 天
location ~ \.(js|css)$ {
    expires      7d;
    add_header Cache-Control "public, immutable";
}

加上了 immutable 标记,浏览器在缓存有效期内不会再发条件请求(If-Modified-Since/ETag)去验证文件是否更新,进一步减少请求。

确认 HTTP/2

站点配置中已经包含 listen 443 ssl http2;,HTTP/2 多路复用已在运行。


第五步:MySQL 优化

数据库只有不到 1MB,表结构很简单。对所有 MyISAM 表执行了 OPTIMIZE 整理碎片,并为文章内容表的 createdstatus+type 字段添加了索引,加速文章查询。


优化前后对比

指标优化前优化后提升
TTFB(服务器本地)~1.71s~0.38s↓ 78%
静态文件来源百度 CDN(外部)本地服务器零外部依赖
CSS/JS 缓存12h7d + immutable减少 14 倍请求
字体缓存365d + immutable一次性加载
OPcache禁用128MB 共享内存PHP 编译缓存
display_errorsOn(安全隐患)Off安全提升

总结

这次优化让我意识到一个教训:很多性能问题不是硬件的锅,而是软件配置的疏忽。 服务器配置不差,OPcache 也编译进去了,就是没人去把配置项前面的分号去掉。

如果你也用 Typecho/WordPress 这类 PHP 博客,建议先检查:

  1. OPcache 是否真的启用了(用 phpinfo 验证,不是看 php -v)
  2. 主题的 CDN 配置能否改成本地
  3. Nginx 有没有给静态文件加缓存头

以上三步零成本、零代码改动,但带来的性能提升是实实在在的。

Last modification:June 9th, 2026 at 04:11 am
如果觉得我的文章对你有用,请随意赞赏