从能用到好用-快速搭建高性能WordPress指南
本文最后更新于 2021年03月10日

注意:本文的所有代码都可以不用看,有一键启动的 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项目

效果展示

vSi8pw
i27pBt
msL3yN
7qs86u
adhBcB
原创声明
本文由 NG6 于2021年02月26日发表在 sleele的博客
如未特殊声明,本站所有文章均为原创;你可以在保留作者及原文地址的情况下转载
转载请注明:从能用到好用-快速搭建高性能WordPress指南 | sleele的博客

评论

  1. herozmy
    Macintosh Chrome
    已编辑
    3月前
    2024-1-30 22:36:48

    感谢

  2. kanon
    Macintosh Edge
    6月前
    2023-10-24 20:07:36

    你好,想请教一下,docker-compose里为什么要把容器ip固定呀,直接在同一docker网络下,用容器名称直接访问不是也可以吗

  3. yy
    Macintosh Edge
    11月前
    2023-5-16 13:23:51

    redis 缓存和 nginx fastcgi 缓存能同时用吗?

    • yy
      yy
      Macintosh Edge
      11月前
      2023-5-16 13:58:42

      @yy 好像redis cache 那个插件是缓存object,而nginx fastcgi 是缓存页面,两使用好像没有冲突,还希望作者来解释下

      • NG6
        yy
        博主
        Macintosh Safari
        11月前
        2023-5-16 15:03:11

        @yy 不冲突,可以一起使用,也建议一起使用

        • yy
          NG6
          Macintosh Edge
          11月前
          2023-5-16 21:46:15

          @NG6 好的,感谢。打开redis cache遇到问题,登陆WP管理页面后,访问其它页面很大机率就跳转到登陆页面。关闭了redis cache插件就好了。之前也是依据你的配置文件来的,不知道在ARM 64下为什么不行了,以后再研究下怎么解决。若解决了再跟帖说明。

  4. ibolee
    Android Chrome
    2年前
    2022-3-22 21:35:02

    很好的文章,不过nginx调优我也是头一次看。有的wp用apache是为了兼容一些老插件,不知大佬有没有apache的调优思路?

  5. 虎虎生威
    Windows Chrome
    2年前
    2022-2-07 22:18:41

    一键搭建完了后反代wordpress总是失败,不会改一键里面的nginx,自己又搭了一个nginxwebui来获取证书+反代,开启后或者wp的格式错了,或者ssl就打不开。小白暂时放弃…………~_~

  6. mo
    Windows Chrome
    3年前
    2021-2-28 13:05:32

    yml 里面 ports是在nginx下面吧

    • NG6
      mo
      博主
      Macintosh Chrome
      3年前
      2021-2-28 13:53:36

      @mo 是的,已更正

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇
下一篇