注意:本文的所有代码都可以不用看,有一键启动的 docker-compose.yml
文件,直接拖动到文章最后即可下载配置文件
目录
前言
之前已经写过几篇WordPress性能优化文章了,但是还不够。面对访问量大的情况下还是有可能发生宕机,没办法服务器资源有限又跑了不少其他服务
如果想要再继续降低资源使用率,就要从根源下手了
博主的服务器基本信息
博主目前使用的服务器性能低下,2C1G。跑了多个服务,资源吃紧,特别是内存。为了提升稳定性,使用了大量swap,降低内存占用就成了首要工作
优化思虑
首先要整理一下优化思路
目前最占用内存的应用就是MySQL,所以要降低内存使用首先就要调整MySQL参数。不过MySQL的内存降下去了,但是数据库查询使用的CPU反倒没有降低,这时候可以通过加入Redis做缓存来提升性能。
WordPress自身也很耗费CPU和内存,这块可以通过静态化解决,理清思路就可以着手优化了
优化措施
前面已经理清了优化思路,剩下的就是动手操作和测试了
不过如果要方方面面都讲清楚很难,我就直接上docker-compose.yml
和配置文件了,这套方案经过长期的的使用,足够稳定,大家可以直接一键部署
MySQL 5.7 内存占用优化
MySQL 5.5的资源占用情况还算不错,但是太老旧了,WordPress官方推 MySQL 5.7
优化 MySQL 5.7 的内存占用非常简单,编辑/etc/mysql/mysql.conf.d/mysqld.cnf
,在[mysqld]
下方添加如下代码即可
博主的MySQL从200M+降低到80M,效果非常明显
[mysqld]
# Memory optimization
performance_schema_max_table_instances=200
table_definition_cache=100
table_open_cache=100
Redis缓存
使用Redis做数据库缓存,能够有效减少MySQL的查询次数
NGINX Fastcgi 缓存
常见的WordPress缓存形式我之前已经介绍过,想要了解的可以参考之前的文章
这次介绍的是性能更好的NGINX缓存,由于需要编辑NGINX文件,对于新手来说过于复杂,具体的我就不过多讲解了,配置文件注释都写了,想了解的可以自己翻看
使用NGINX Fastcgi后,访问文章页面从60~90%的CPU占用率降低到个位数,效果拔群
注1:原本的NGINX是没有Fastcgi 缓存清理模块的,我编译了一份带有缓存清理模块的NGINX,并封装了docker image
注2:使用 NGINX Fastcgi缓存
需要安装WordPress插件 Nginx-Helper
注3:目前nginx-helper无法清除中文url的文章缓存(不太确定,在本地调试时可以清除中文url路径的缓存,但是生产环境却不行,英文路径可以),已经向作者提issue了,不过估计不会被理会,如果有大手子知道怎么改请务必告诉我,谢谢
2021.03.05更新
读一下nginx-helper的源码,关于cache_path的获取,是通过对url进行hash,这段内容在class-purger.php中
// Build a hash of the URL.
$hash = md5( $url_data['scheme'] . 'GET' . $url_data['host'] . $url_path );
// 这块以下都不用管
// Ensure trailing slash.
$cache_path = RT_WP_NGINX_HELPER_CACHE_PATH;
$cache_path = ( '/' === substr( $cache_path, -1 ) ) ? $cache_path : $cache_path . '/';
// 设置缓存路径,如果和nginx生成的缓存路径不匹配。则无法删除缓存
// Set path to cached file.
$cached_file = $cache_path . substr( $hash, -1 ) . '/' . substr( $hash, -3, 2 ) . '/' . $hash;
由于生成的md5对不上,经过一番调试,我发现是url地址获取有误,并非大小写问题,根据nginx的配置和生成的key,可以得知,key如何生成的,逐个测试就好了,我的情况是,经过反代或cloudflare后,$url_data['host']
获取有误,所以手动填写前半段即可,并且path必须改为双引号,单引号不行
// Build a hash of the URL.
$hash = md5( 'httpGETsleele.com' . $url_data["path"] );
// Ensure trailing slash.
$cache_path = RT_WP_NGINX_HELPER_CACHE_PATH;
$cache_path = ( '/' === substr( $cache_path, -1 ) ) ? $cache_path : $cache_path . '/';
// Set path to cached file.
$cached_file = $cache_path . substr( $hash, -1 ) . '/' . substr( $hash, -3, 2 ) . '/' . $hash;
可选项:修改缓存位置
例:
缓存位置请编辑,wp-config.php 添加
define( 'RT_WP_NGINX_HELPER_CACHE_PATH','/tmp/wpcached');
或 编辑Nginx-Helper代码 class-nginx-helper.php
,修改路径为
define( 'RT_WP_NGINX_HELPER_CACHE_PATH','/tmp/wpcached');
server {
listen 80 ;
listen [::]:80;
root /var/www/html;
# Add index.php to the list if you are using PHP
index index.php;
server_name _;
set $skip_cache 0;
# post 访问不缓存
if ($request_method = POST) {
set $skip_cache 1;
}
# 动态查询不缓存
if ($query_string != "") {
set $skip_cache 1;
}
# 后台等特定页面不缓存(其他需求请自行添加即可)
if ($request_uri ~* "/wp-admin/|/xmlrpc.php|wp-.*.php|/feed/|index.php|sitemap(_index)?.xml|nginx.log") {
set $skip_cache 1;
}
# 对登录用户、评论过的用户不展示缓存(建议禁用登录和评论用户的缓存,不要删除这里面的内容就对了,默认设置非常合理)
if ($http_cookie ~* "comment_author|wordpress_[a-f0-9]+|wp-postpass|wordpress_no_cache|wordpress_logged_in") {
set $skip_cache 1;
}
# 不要乱改ip地址
location ~ [^/]\.php(/|$) {
try_files $uri =404;
fastcgi_pass 172.19.0.4:9000;
fastcgi_index index.php;
include fastcgi.conf;
# 获取真实IP
set_real_ip_from 172.19.0.0/16;
real_ip_header X-Forwarded-For;
real_ip_recursive on;
# 新增的缓存规则
fastcgi_cache_bypass $skip_cache;
fastcgi_no_cache $skip_cache;
add_header X-Cache "$upstream_cache_status From $host";
fastcgi_cache WORDPRESS;
fastcgi_cache_valid 200 301 302 304 1d;
fastcgi_cache_valid 404 10m;
}
location / {
try_files $uri $uri/ /index.php?$args;
}
# 缓存清理配置(可选模块,请细看下文说明)
location ~ /purge(/.*) {
allow 127.0.0.1;
# 默认是所以人都可以清理缓存,设置为只能自己清理,请把下面的ip段改为自己服务器的ip
allow 172.19.0.0/16;
deny all;
fastcgi_cache_purge WORDPRESS "$scheme$request_method$host$1";
}
location ~* ^.+\.(ogg|ogv|svg|svgz|eot|otf|woff|mp4|ttf|rss|atom|jpg|jpeg|gif|png|ico|zip|tgz|gz|rar|bz2|doc|xls|exe|ppt|tar|mid|midi|wav|bmp|rtf)$ {
access_log off;
log_not_found off;
expires max;
}
location = /robots.txt {
access_log off;
log_not_found off;
}
location ~ /\. {
deny all;
access_log off;
log_not_found off;
}
}
其他优化措施
往期文章
将NGINX缓存放入内存盘
非常简单
将缓存位置挂载到宿主机的/dev/shm/路径即可
- /dev/shm/nginx-cache:/var/run/nginx-cache
使用WEBP替换JPG、PNG
这个以后单独再写一篇,jpg,png转换到webp的性能需求太高了,上传一张图片需要很久,cpu还会被占满,性能低的机器用不起,目前的我构想是:把图片提前转换成webp,然后使用GitHub Action定期转换仓库的图片,但是实施起来没有预想的简单,外链图片不知道怎么自动选择,webp express
插件没有产生效果
https://hub.docker.com/r/webpsh/webps
一键部署高性能WordPress
注:请先安装docker和docker-compose
我估计大部分人应该都不愿意在性能优化这块折腾太多,毕竟不是每个人都懂WordPress和相关工具的配置(我自己也不是很懂),WordPress是拿来写作的,专注写作最重要
下载wordpress-blog.zip
,解压后拖到服务器,进入到 wordpress-blog
目录,docker-compose up -d
启动即可
使用前最好改一下数据库的密码
ip请不要改动,除非你明确知道你在做什么
所有生成数据均在wordpress-blog文件夹中
默认最大上传文件2GB
version: '3.1'
services:
wordpress:
image: wordpress:5-fpm
restart: always
networks:
wordpress_net:
ipv4_address: 172.19.0.4
environment:
WORDPRESS_DB_HOST: db
WORDPRESS_DB_USER: exampleuser
WORDPRESS_DB_PASSWORD: examplepass
WORDPRESS_DB_NAME: exampledb
volumes:
- /usr/share/zoneinfo/Asia/Shanghai:/etc/localtime:ro
- $PWD/wordpress:/var/www/html
# - /dev/shm/nginx-cache:/var/run/nginx-cache
- $PWD/nginx-cache:/var/run/nginx-cache
- $PWD/nginx/uploads.ini:/usr/local/etc/php/php.ini
depends_on:
- redis
- db
redis:
image: redis:5
restart: always
networks:
wordpress_net:
ipv4_address: 172.19.0.3
volumes:
- /usr/share/zoneinfo/Asia/Shanghai:/etc/localtime:ro
- $PWD/redis-data:/data
depends_on:
- db
db:
image: mysql:5.7
restart: always
networks:
wordpress_net:
ipv4_address: 172.19.0.2
environment:
MYSQL_DATABASE: exampledb
MYSQL_USER: exampleuser
MYSQL_PASSWORD: examplepass
MYSQL_RANDOM_ROOT_PASSWORD: '1'
volumes:
- /usr/share/zoneinfo/Asia/Shanghai:/etc/localtime:ro
- $PWD/mysql:/var/lib/mysql
- $PWD/nginx/mysqld.cnf:/etc/mysql/mysql.conf.d/mysqld.cnf
web:
image: superng6/nginx:debian-stable-1.18.0
restart: always
networks:
wordpress_net:
ipv4_address: 172.19.0.5
ports:
- 80:80
volumes:
- /usr/share/zoneinfo/Asia/Shanghai:/etc/localtime:ro
- $PWD/nginx/nginx.conf:/etc/nginx/nginx.conf
- $PWD/nginx/default.conf:/etc/nginx/conf.d/default.conf
- $PWD/nginx/fastcgi.conf:/etc/nginx/fastcgi.conf
# - /dev/shm/nginx-cache:/var/run/nginx-cache
- $PWD/nginx-cache:/var/run/nginx-cache
- $PWD/wordpress:/var/www/html
depends_on:
- wordpress
networks:
wordpress_net:
driver: bridge
ipam:
config:
- subnet: 172.19.0.0/16
注意1:本配置文件默认没有开启HTTPS,如果需要HTTPS建议外面再套一层NGINX反代
注意2:记得先注释掉docker-compose中开放80端口
注意3: 反代地址 172.19.0.5
其他
我编译了两个版本的docker nginx镜像,分别上基于debian和alpine,基于目前最新nginx稳定版1.18.0,添加了brotli和cache_purge模块
大家可以按照自己喜好来:https://github.com/SuperNG6/docker-nginx
注意:brotli仅在https生效
brotli on;
brotli_comp_level 5;
brotli_static on;
brotli_types
application/atom+xml
application/javascript
application/json
application/rss+xml
application/vnd.ms-fontobject
application/x-font-ttf
application/x-font-opentype
application/x-font-truetype
application/x-javascript
application/x-web-app-manifest+json
application/xhtml+xml
application/xml
font/eot
font/opentype
font/otf
image/svg+xml
image/x-icon
image/vnd.microsoft.icon
text/css
text/plain
text/javascript
text/x-component;
结尾
虽然标题带有 一键
,但是硬要说话,还是带有不小的门槛的。确实可以一键启动,但在已经部署好WordPress情况下,开启NGINX缓存,配置缓存清理插件,Redis的设置等后续操作,还是需要自己手动来的。
不过相信我,这已经是最最简单能够实现开启NGINX缓存、优化数据库内存占用的WordPress安装方式了,没有之一,最复杂的工作我已经做完了。
PS:NGINX配置文件也适用于其他PHP项目
效果展示
本文由 NG6 于2021年02月26日发表在 sleele的博客
如未特殊声明,本站所有文章均为原创;你可以在保留作者及原文地址的情况下转载
转载请注明:从能用到好用-快速搭建高性能WordPress指南 | sleele的博客
服务器那些搞好了,就是装些插件优化了
感谢
你好,想请教一下,docker-compose里为什么要把容器ip固定呀,直接在同一docker网络下,用容器名称直接访问不是也可以吗
redis 缓存和 nginx fastcgi 缓存能同时用吗?
@yy 好像redis cache 那个插件是缓存object,而nginx fastcgi 是缓存页面,两使用好像没有冲突,还希望作者来解释下
@yy 不冲突,可以一起使用,也建议一起使用
@NG6 好的,感谢。打开redis cache遇到问题,登陆WP管理页面后,访问其它页面很大机率就跳转到登陆页面。关闭了redis cache插件就好了。之前也是依据你的配置文件来的,不知道在ARM 64下为什么不行了,以后再研究下怎么解决。若解决了再跟帖说明。
很好的文章,不过nginx调优我也是头一次看。有的wp用apache是为了兼容一些老插件,不知大佬有没有apache的调优思路?
一键搭建完了后反代wordpress总是失败,不会改一键里面的nginx,自己又搭了一个nginxwebui来获取证书+反代,开启后或者wp的格式错了,或者ssl就打不开。小白暂时放弃…………~_~
yml 里面 ports是在nginx下面吧
@mo 是的,已更正