WordPress 安装很方便,可以说是开箱即用。但是随着文章增多,访问量增大,会发现 WordPress 很“慢”。这是 WordPress 本身的 PHP 运行机制导致的,每篇文章都要去数据库读取,而且 WordPress 为了支持各种功能,现在已经非常臃肿,每次请求都要加载很多东西。但正是 WordPress 的功能强大,让我们也能很方便的做各种优化。
0x1 使用最新版本的 PHP 和 MySQL
毫无疑问升级基础运行环境是提高性能最好的方式之一。特别的 PHP7 和 MySQL 5.7 较之前的版本性能提升很大。还可以根据服务器配置适当调整 PHP-FPM 和 MySQL 参数。
0x2 使用缓存
这里的缓存有两层意思,一是 PHP 层面的运行数据缓存,二是文章页面静态化。这里推荐几个插件来解决这个问题:
Redis Object Cache
一款持久对象缓存插件。其实 WordPress 本身带有对象缓存功能,但是是把序列化的对象缓存在文件中,效果不是很好。这个插件通过重写 object-cache.php 文件,把对象缓存到 Redis。直观的感受就是不光前台页面加载速度快了,而且后台响应速度提升更大。
Cache Enabler
keycdn 公司开发的一款页面静态化缓存的插件。相比 wp-supercache 等插件更加简洁和强大。建议按照官方说明进行增强设置,官方的配置有一点小问题,当你的永久链接格式设置为 xxx.html 时 $cache_uri(默认是 $request_uri)没有后面的 / 拼凑的文件路径不对(xxx.htmlindex.html),需要改成 ${cache_uri}/index.html,这样虽然访问首页时中间会多个 / 但也不影响。
1 2 3 4 5 6 | # default html file set $cache_enabler_uri '${custom_subdir}/wp-content/cache/cache-enabler/${http_host}${cache_uri}/index.html'; # webp html file(按需开启) if ($http_accept ~* "image/webp") { set $cache_enabler_uri '${custom_subdir}/wp-content/cache/cache-enabler/${http_host}${cache_uri}/index-webp.html'; } |
我使用的是 Nginx,除了正常设置 gzip 外还开启了 gzip_static 参数,让 Nginx 在读取文件的时候优先读取带 gz 后缀的静态文件,不用再做 gzip 压缩。
顺带推荐一个 gzip 检查网站:https://www.giftofspeed.com/gzip-test/
不过使用高级设置后需要把缓存有效期设置为 0(永不失效),可能会造成缓存不会被更新(正常情况下更新文章缓存会被更新)。这里我是通过删除缓存文件然后访问自己 sitemap 中的链接来刷新缓存:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 | #!/usr/bin/env python3 # -*- coding: utf-8 -*- # rebuild cache according to sitemap.xml import os import requests import xml.etree.ElementTree as ET import time import shutil CACHE_DIR = "/var/www/wordpress/wp-content/cache/cache-enabler/" SITEMAP_URL = "https://iyaozhen.com/sitemap.xml" if os.path.isdir(CACHE_DIR): shutil.rmtree(CACHE_DIR) try: sitemap = requests.get(SITEMAP_URL) except (requests.HTTPError, requests.ConnectionError) as e: print("get sitemap.xml error: %s" % e) else: urlset = ET.fromstring(sitemap.content) print("start rebuild cache at %s" % time.asctime()) for url in urlset: loc = url[0].text try: requests.get(loc) except (requests.HTTPError, requests.ConnectionError) as e: print("request %s error: %s" % (loc, e)) else: print("hit %s" % loc) finally: time.sleep(0.1) else: print("no cache dir: %s" % CACHE_DIR) |
https://gist.github.com/iyaozhen/53e6a57a2f7e945ba1161953959a7cb2
Nginx open_file_cache
上一步我们已经将网站静态化,访问一般的文章页面,其实相当于打开 html 文件,但文件打开关闭也是有开销的,这个能否优化呢?答案是可以的,nginx 提供了 open_file_cache 功能,简单配置即可
1 | open_file_cache max=100 inactive=3600s; |
此配置是让 nginx work 保持最常访问的文件句柄,不是缓存文件内容(nginx 发送文件是内核态直接发送的,不用应用层用户态保持文件内容),对于中小站点很实用,我们可以通过 sudo lsof -p pid
查看进程打开的文件句柄。这一通骚操作后,TTFB 能降到 10ms 以下。
0x3 使用 CDN 和图片压缩
用户有时候感觉网站慢,更多的是静态资源加载慢。页面上的 JS、CSS、图片等都需要消耗服务器带宽。而且中国地域辽阔,跨地区、跨运营商更是问题。这时就需要 CDN 了。现在国内各个云都在相互竞争,CDN 比较便宜,免费的也有很多。我之前使用的是七牛云,不过自从服务器迁到腾讯云之后, CDN 也换到了腾讯(免费12个月)。这里推荐同为 keycdn 出的 CDN Enabler 插件,能将页面中的链接替换为 CDN 链接。同时推荐使用 WP Smush、Compress JPEG & PNG images 压缩图片(有条件的还可以付费开启 webp),还有使用 BJ Lazy Load 实现图片懒加载(显著提高首屏加载速度)。最后不要忘记站点和 CDN 都配置一下防盗链。
0x4 升级到 HTTP2
HTTP2 支持请求复用,能提高50-70%的加载速度。首先要配置 HTTPS,再简单的配置下就能支持 HTTP2 了。当然静态资源使用的 CDN 最好也要支持 HTTP2,目前国内厂商基本都支持。