我最近安装了 WordPress 6,并在 Docker 上运行了 MariaDB 和 PHP 8 FPM。有时,前端的请求在主 HTML 文档上的响应时间很慢。在此示例中,其中一个类别页面花费了 1.8 秒:
由于所有查询仅花费 0.06 秒,并且根据插件,我们没有外部 HTTP 调用,因此我无法解释为什么会发生这种情况。通常我们有 ~300-400ms,这仍然有点高,但比 ~1.8s 更容易接受。
PHP FPM 的 slowlog 跟踪仅显示
php | [30-Jul-2022 10:50:46] WARNING: [pool www] child 26, script '/www/index.php' (request: "GET /wp/index.php?category/software/") executing too slow (1.170804 sec), logging
php | [30-Jul-2022 10:50:46] NOTICE: child 26 stopped for tracing
php | [30-Jul-2022 10:50:46] NOTICE: about to trace 26
php | [30-Jul-2022 10:50:46] [pool www] pid 26
php | script_filename = /www/index.php
php | [0x00007f86db6129c0] [INCLUDE_OR_EVAL]() /www/wp-config.php:110
php | [0x00007f86db612720] [INCLUDE_OR_EVAL]() /www/wp-load.php:50
php | [0x00007f86db612190] [INCLUDE_OR_EVAL]() /www/wp-blog-header.php:13
php | [0x00007f86db612090] [INCLUDE_OR_EVAL]() /www/index.php:17
php | [30-Jul-2022 10:50:46] NOTICE: finished trace of 26
这对我来说似乎没什么用,因为这行wp-config.php
只包含
110 require_once(ABSPATH . 'wp-settings.php');
并且wp-settings.php
它本身是一个非常大的脚本,包括大量其他 php 文件。因此,我找不到任何方法来分析导致这种大规模减速的原因。
我的 PHP-FPM 配置
log_level = notice
error_log = /proc/self/fd/2
[www]
; if we send this to /proc/self/fd/1, it never appears
access.log = /proc/self/fd/2
;access.log = /dev/null
clear_env = no
user = www-data
group = www-data
listen = 127.0.0.1:9000
;pm = dynamic
;pm.max_children = 40
;pm.start_servers = 20
;pm.min_spare_servers = 10
;pm.max_spare_servers = 25
;pm.max_requests = 200
pm = static
pm.max_children = 40
pm.start_servers = 10
pm.min_spare_servers = 10
pm.max_spare_servers = 20
pm.max_requests = 100
; https://www.kevinhooke.com/2018/02/27/nginx-php5-fpm-response-lag-on-first-requests/
pm.process_idle_timeout = 10s
pm.status_path = /status
slowlog = /proc/self/fd/2
request_slowlog_timeout = 1s
catch_workers_output = yes
env[TMP] = /tmp
env[TMPDIR] = /tmp
env[TEMP] = /tmp
由于这是一个测试环境,因此没有外部流量。我也在 PHP-FPM 状态页面上验证了这一点,其中大多数工作程序处于空闲状态。有时页面加载速度甚至更慢(最多 8 秒),这取决于时间,这看起来像是负载问题,但事实并非如此。即使是运行这些容器的裸机服务器,负载也很低:
Load average: 0.38 0.60 0.59
编辑
我注意到,当我重新启动 Nginx + PHP-FPM(两者都在单个 Compose 文件中,MariaDB 在单独的文件中)时,页面加载时间要快得多。但这并不能永久解决问题,一段时间后它又变慢了。我已经尝试减少pm.max_requests = 100
,之前是 500,但没有解决问题。
答案1
我发现我犯了一个愚蠢的错误:由于这是一个测试环境,我将 PHP 容器的内存限制减少到docker-compose.yml
1 GB
services:
test-php:
# ...
mem_limit: 1G
之前设置为 2 GB,因为在生产安装中,平均脚本内存消耗 * 子进程将计算为 1.7 GB。我在测试环境中忘记了这一点,因此发生了以下情况:PHP 生成多个进程并且不释放内存。这会在一些请求之后填满容器内存,从而导致页面加载时间变慢。
这非常令人困惑,因为过了一段时间,我还在日志中看到了 MySQLi 错误,这让我去查看数据库,结果却被误导了。这只是对数据库的调用,或者发布的日志条目中的配置,其中容器的内存是满的已到达极限。