默认安装的 WordPress 性能表现很一般,尤其如果添加了 woocommerce 插件后,后台总有一种卡顿的感觉,为了提升 WordPress/woocommerce 的使用体验,需要进行一些性能优化操作。WordPress 本身是一个基于 PHP 实现的程序,因此要优化使用体验就要在 LNMP/LAMP 架构的组件配置上进行调整。这篇文章介绍一些 LNMP 架构中,对于 WordPress 性能有影响的配置项,理论上应该也适用于其他 PHP 项目。
注意:本篇文章需要技术背景。
一、Nginx配置
sendfile on;
tcp_nopush on;
tcp_nodelay on;
keepalive_timeout 60;
1.1 GZIP压缩
gzip on;
gzip_vary on;
gzip_disable "msie6";
gzip_min_length 1k;
gzip_comp_level 5;
gzip_types text/plain text/css application/json application/x-javascript text/xml application/xml application/xml+rss text/javascript application/javascript application/x-httpd-php;
1.2 静态缓存
location ~.*\.(js|css|html|png|jpg|jpeg|gif|gz|svg|mp4|ogg|ogv|webm|htc|xml|woff|zip|webp)$
{
access_log off;
expires 30d;
try_files $uri =404;
}
二、PHP配置
2.1 opcache配置
[opcache]
; 启用opcache
opcache.enable = 1
; opcache使用的内存量
opcache.memory_consumption = 256M
; 存储字符串的缓冲区大小,单位是MB
opcache.interned_strings_buffer = 32
; 可存储的脚本文件数量上限
opcache.max_accelerated_files = 1979
; 设置重新验证脚本缓存的频率,以秒为单位。如果设置为0,则每次请求都会重新验证缓存
opcache.revalidate_freq = 60
; 启用或禁用时间戳验证。如果启用此功能,OPcache会在每次请求时检查脚本的时间戳以确定是否需要重新加载脚本
opcache.validate_timestamps = 0
; 启用会将缓存持久化到文件
opcache.file_cache = 0
; 是否将注释保存到缓存中,如果依赖注释中的注解需要启用,wordpress中没有使用
opcache.save_comments = 0
; php8以上版本启用jit
opcache.jit = 1235
opcache.enable_cli = 1
三、WordPress调整
可以通过直接修改WordPress配置文件(wp-config.php)或者安装插件进行的优化项目。
3.1 关闭默认的CRON执行器
define( 'DISABLE_WP_CRON', true );
可以通过系统的crontab来执行定时任务:
# 修改crontab配置
crontab -e
# 添加下面行
* * * * * php -f /path/to/wp-cron.php
3.2 静态文件压缩
define( 'COMPRESS_CSS', true ); // 压缩CSS
define( 'COMPRESS_SCRIPTS', true ); // 压缩JS
define( 'ENFORCE_GZIP', true ); // 强制启用GZIP,如果WEB服务器启用了GZIP可以不开启
define( 'CONCATENATE_SCRIPTS', true ); // 连接脚本
3.3 插件优化
插件也会对WordPress的性能有很大影响,有一些优秀的插件会极大优化WordPress性能表现,可以参考下面文章。
四、MySQL/MariaDB数据库配置优化
4.1 数据库配置优化
适用于小型实例,中大型示例参考参数备注进行调整。数据库my.cnf配置文件中添加以下配置:
# 表定义缓存数量,最低400
table_definition_cache = 400
# 打开表缓存
table_open_cache = 500
# 关闭performance_schema,大型实例不建议采用,大概能节省数据库默认占用一半的内存
performance_schema = off
# innodb的缓存
# 数值越大,内存中占用越大,同时数据库性能也会提高。纯数据库服务器可以使用内存的 70%-80% 。
# 单机部署时最好多测试一下
innodb_buffer_pool_size = 256M
# 尽可能增加innodb_buffer_pool_size
innodb_buffer_pool_size = 512M
# 决定了事务日志何时被写入并刷新到磁盘上
# 0:每秒将日志写入并刷新到磁盘
# 1:每次事务提交时,都将日志写入并刷新到磁盘
# 2:每次事务提交时,都将日志写入日志缓冲区,但仅在每秒刷新到磁盘
# 选择0/2,宕机时有可能丢失1秒内事务数据
innodb_flush_log_at_trx_commit = 0
4.2 持久化数据库连接
查看WordPress性能团队的聊天记录突然发现WordPress默认情况下是没有启用持久连接的(数据库连接池),会导致每一次的请求都需要初始化数据库连接。解决办法比较简单,在 wp-content
目录下放一个 db.php
文件,写入以下内容,然后在配置文件中添加一个值为 true
的 DB_PERSIST
常量即可。
这个小问题应该会在不久的未来经过测试后合并到WordPress核心中,此方法只适用于未合并前的这段时间,合并后就不需要了,目前6.5.2版本暂时还没有提供。
关于PHP中的持久化连接,有兴趣可以参考官网中以下两篇文章:
<?php
if ( !class_exists('wpdb') ) {
require_once ABSPATH . WPINC . '/class-wpdb.php';
}
class custom_wpdb extends wpdb {
/**
* Connects to and selects database.
*
* If `$allow_bail` is false, the lack of database connection will need to be handled manually.
*
* @since 3.0.0
* @since 3.9.0 $allow_bail parameter added.
*
* @param bool $allow_bail Optional. Allows the function to bail. Default true.
* @return bool True with a successful connection, false on failure.
*/
public function db_connect( $allow_bail = true ) {
$this->is_mysql = true;
$client_flags = defined( 'MYSQL_CLIENT_FLAGS' ) ? MYSQL_CLIENT_FLAGS : 0;
/*
* Set the MySQLi error reporting off because WordPress handles its own.
* This is due to the default value change from `MYSQLI_REPORT_OFF`
* to `MYSQLI_REPORT_ERROR|MYSQLI_REPORT_STRICT` in PHP 8.1.
*/
mysqli_report( MYSQLI_REPORT_OFF );
$this->dbh = mysqli_init();
$host = $this->dbhost;
$port = null;
$socket = null;
$is_ipv6 = false;
$host_data = $this->parse_db_host( $this->dbhost );
if ( $host_data ) {
list( $host, $port, $socket, $is_ipv6 ) = $host_data;
}
/*
* If using the `mysqlnd` library, the IPv6 address needs to be enclosed
* in square brackets, whereas it doesn't while using the `libmysqlclient` library.
* @see https://bugs.php.net/bug.php?id=67563
*/
if ( $is_ipv6 && extension_loaded( 'mysqlnd' ) ) {
$host = "[$host]";
}
if ( DB_PERSIST ) {
$host = 'p:' . $host;
}
if ( WP_DEBUG ) {
mysqli_real_connect( $this->dbh, $host, $this->dbuser, $this->dbpassword, null, $port, $socket, $client_flags );
} else {
// phpcs:ignore WordPress.PHP.NoSilencedErrors.Discouraged
@mysqli_real_connect( $this->dbh, $host, $this->dbuser, $this->dbpassword, null, $port, $socket, $client_flags );
}
if ( $this->dbh->connect_errno ) {
$this->dbh = null;
}
if ( ! $this->dbh && $allow_bail ) {
wp_load_translations_early();
// Load custom DB error template, if present.
if ( file_exists( WP_CONTENT_DIR . '/db-error.php' ) ) {
require_once WP_CONTENT_DIR . '/db-error.php';
die();
}
$message = '<h1>' . __( 'Error establishing a database connection' ) . "</h1>\n";
$message .= '<p>' . sprintf(
/* translators: 1: wp-config.php, 2: Database host. */
__( 'This either means that the username and password information in your %1$s file is incorrect or that contact with the database server at %2$s could not be established. This could mean your host’s database server is down.' ),
'<code>wp-config.php</code>',
'<code>' . htmlspecialchars( $this->dbhost, ENT_QUOTES ) . '</code>'
) . "</p>\n";
$message .= "<ul>\n";
$message .= '<li>' . __( 'Are you sure you have the correct username and password?' ) . "</li>\n";
$message .= '<li>' . __( 'Are you sure you have typed the correct hostname?' ) . "</li>\n";
$message .= '<li>' . __( 'Are you sure the database server is running?' ) . "</li>\n";
$message .= "</ul>\n";
$message .= '<p>' . sprintf(
/* translators: %s: Support forums URL. */
__( 'If you are unsure what these terms mean you should probably contact your host. If you still need help you can always visit the <a href="%s">WordPress support forums</a>.' ),
__( 'https://wordpress.org/support/forums/' )
) . "</p>\n";
$this->bail( $message, 'db_connect_fail' );
return false;
} elseif ( $this->dbh ) {
if ( ! $this->has_connected ) {
$this->init_charset();
}
$this->has_connected = true;
$this->set_charset( $this->dbh );
$this->ready = true;
$this->set_sql_mode();
$this->select( $this->dbname, $this->dbh );
return true;
}
return false;
}
}
global $wpdb;
$dbuser = defined( 'DB_USER' ) ? DB_USER : '';
$dbpassword = defined( 'DB_PASSWORD' ) ? DB_PASSWORD : '';
$dbname = defined( 'DB_NAME' ) ? DB_NAME : '';
$dbhost = defined( 'DB_HOST' ) ? DB_HOST : '';
$wpdb = new custom_wpdb( $dbuser, $dbpassword, $dbname, $dbhost );
配置文件中:
define( 'DB_PERSIST', true );
以上就是LNMP架构中各组件的一些优化配置,文章持续更新中。
发表回复