WordPress 优化手记

由于本站使用的主机内存非常小,只有区区 512M,之前 WordPress 运行速度较慢,mysql 也经常崩溃。最近花了点时间查了查资料,试着彻底解决这个问题,特记录以下优化过程。

优化前后架构对比

首先上两张架构图,展示优化前和优化后的架构对比和优化思路。在优化前,网站的架构基本是最原始的 LAMP 架构,MySQL、PHP 以及 Apahce 都没有经过调优:

优化前架构

优化后引入了一些新的组件:

  1. 使用 Multi-processing Module (MPM) 提高 Apache 并发处理 HTTP 请求的能力。
  2. 使用 PHP 的 FastCGI 模块来提高 PHP 多进程处理的能力。PHP-FPM 具有驻留内存的能力,配合 Apahce MPM 可以显著提高 HTTP 请求的并发处理速度。
  3. 引入一个 MySQL Mon 的 cron job,来监控 mysqld 进程,当 mysqld 可能因为内存不足被系统 kill 时,可以立即重启 MySQL。当然这只是辅助手段,最重要的是优化 MySQL 的内存使用。
  4. 引入 Cloudflare 服务作为 CDN,可以极大加速网站内容访问的速度。
优化后架构

优化 Mysql

首先根据根据资料对 MySQL 的内存使用进行调优。根据需要对下列参数进行调整,然后重启 mysql 服务并使用 vmstat 观察内存使用情况。

[mysqld]
key_buffer_size = 8

# Tuning
key_buffer = 32M
thread_stack = 192K
thread_cache_size = 2
innodb_buffer_pool_size = 8M
innodb_buffer_pool_size = 8M
max_connections = 50
max_allowed_packet = 1M
query_cache_limit = 2M
query_cache_size = 16M
tmp_table_size = 32M
table_open_cache = 64
thread_concurrency = 4

最后简单写了个脚本加在 crontab 里每分钟执行一次,用来在 MySQL 万一崩溃了之后可以立即重启 MySQL 服务。脚本内容如下:

#!/bin/bash

ps -ef | grep mysqld | grep -v grep
mysqld=$?

if [[ "$mysqld" == "1" ]]; then
  service mysqld start
fi

优化 Apache

在 /etc/httpd/conf.modules.d/00-mpm.conf 中包含如下内容:

# Select the MPM module which should be used by uncommenting exactly
# one of the following LoadModule lines.

# prefork MPM: Implements a non-threaded, pre-forking web server
# See: http://httpd.apache.org/docs/2.4/mod/prefork.html
#
# NOTE: If enabling prefork, the httpd_graceful_shutdown SELinux
# boolean should be enabled, to allow graceful stop/shutdown.
#
LoadModule mpm_prefork_module modules/mod_mpm_prefork.so

# worker MPM: Multi-Processing Module implementing a hybrid
# multi-threaded multi-process web server
# See: http://httpd.apache.org/docs/2.4/mod/worker.html
#
#LoadModule mpm_worker_module modules/mod_mpm_worker.so

# event MPM: A variant of the worker MPM with the goal of consuming
# threads only for connections with active processing
# See: http://httpd.apache.org/docs/2.4/mod/event.html
#
#LoadModule mpm_event_module modules/mod_mpm_event.so

Apache 默认是启用 mod_mpm_prefork.so,针对这种 MPM 管理模块将下列配置添加到 Apache 配置文件 /etc/httpd/conf/httpd.conf

KeepAlive On
MaxKeepAliveRequests 100
KeepAliveTimeout 2

<IfModule prefork.c>
    StartServers       4
    MinSpareServers    4
    MaxSpareServers    8
    ServerLimit       10
    MaxClients        10
    MaxRequestsPerChild  40
</IfModule>

如果使用的是 mod_mpm_event.so ,它是一种更加轻量级的 MPM 模块,使用的内存更少。将 mod_mpm_prefork.so 注释掉,然后将模块 mod_mpm_event.so 前的注释去掉,修改相应的 Apache 配置如下:

<IfModule mpm_event_module>
    StartServers 2
    MinSpareThreads 25
    MaxSpareThreads 75
    ThreadLimit 64
    ThreadsPerChild 25
    MaxRequestWorkers 150
    MaxConnectionsPerChild 0
</IfModule>

升级 PHP 到较新版本

首先停止 Apache 服务并且移除老版本的 PHP:

$ sudo service httpd stop 
$ sudo yum remove php70-cli php70-common \
php70-json php70-mysqlnd php70-pdo php70-process php70-xml

然后直接安装新版本的 PHP 即可:

$ sudo yum install php73 php73-mysqlnd php73-cli \
php73-common php73-json php73-fpm

使用 PHP-FPM 模块

配置 PHP-FPM 如下:/etc/php-fpm.d/www.conf

; The address on which to accept FastCGI requests.
; listen = /var/run/php-fpm/www.sock
listen = 127.0.0.1:9000
listen.acl_users = apache
pm.max_children = 16
pm.start_servers = 3
pm.min_spare_servers = 2
pm.max_spare_servers = 5

然后就可以启动 PHP-FPM 服务:

$ sudo service php-fpm restart

再观察可以发现 PHP-FPM 已经监听在 9000 端口,然后将如下配置添加到 Apache 的 VirtualHost 里即可。我这里是使用的 HTTPS,因此 VirtualHost 监听的是 443 端口:

<VirtualHost _default_:443>
ProxyPassMatch ^/(.*\.php(/.*)?)$ fcgi://127.0.0.1:9000/var/www/html/$1
</VirtualHost>

使用 CloudFlare 服务

使用 CDN 可以极大地优化网站静态内容访问的速度,CloudFlare 提供了免费的服务,而且体验足够简单,只需简单的几个步骤对域名服务器稍加设置就可以将网站加入到 CloudFlare 的全球内容分发网络中。

其他优化

升级操作系统碰到的问题

17年上线到现在, Amazon Linux 操作系统也已经很久没有升级了,从安全角度有必要把软件包更新到最新版本。但是在升级过程中碰到如下错误:

错误:软件包:rpm-libs-4.11.3-40.76.amzn1.x86_64 (@amzn-updates)
需要:libdb-4.7.so()(64bit)
正在删除: db4-4.7.25-18.11.amzn1.x86_64 (installed)
libdb-4.7.so()(64bit)
取代,由: libdb4-4.8.30-13.el7.x86_64 (epel)
~libdb-4.8.so()(64bit)

最后发现是由于 epel 库中的 libdb 版本和 Amazon Liniux 中默认的包存在冲突,解决的办法是在升级前先禁用 epel,升级完成后在继续恢复。

$ sudo yum-config-manager --disable epel
$ sudo yum clean all
$ sudo yum update
$ sudo yum-config-manager --enable epel

最后比较彻底的方法是在 /etc/yum.repos.d/epel.repo 中增加 exclude=libdb* 即可。

[epel]
name=Extra Packages for Enterprise Linux 7 - $basearch
#baseurl=http://download.fedoraproject.org/pub/epel/7/$basearch
metalink=https://mirrors.fedoraproject.org/metalink?repo=epel-7&amp;arch=$basearch
failovermethod=priority
enabled=1
gpgcheck=1
gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-EPEL-7
exclude=libdb*

优化 SSH 连接时间

由于默认 SSHD 服务的连接超时时间比较短,经常是几分钟后连接就不可用了,非常不方便,因此另外一个简单优化是修改 SSH 客户端的超时时间。修改:/etc/ssh/sshd_config 设置如下:

ClientAliveInterval 30
ClientAliveCountMax 60

优化结果

优化完毕之后观察 vmstat 结果,观察发现 swap 和 swap I/O 内存使用已经比较平稳,WP 整体加载速度也快了很多,目前系统整体运行是比较平稳的。可见不涉及任何开发的系统调优也是个技术活,除了需要对软件、系统有深入的了解外,还需要有足够的耐心。

经过优化后,在插件的加持下,WP 的使用体验还是非常不错的,终于可以愉快地书写了。:-)

参考

87 次阅读

发表评论

电子邮件地址不会被公开。 必填项已用*标注