掘金 后端 ( ) • 2024-04-20 09:57

最近在一个 Nginx + PHP-FPM 的环境下部署 WordPress,访问网站时出现了 504 网关超时错误。经过一番排查和解决,最终网站恢复了正常。在这篇文章中,我将详细记录问题的解决过程,希望对遇到类似问题的朋友有所帮助。

1. 问题描述

WordPress 网站部署在一个 Nginx + PHP-FPM 的环境下。但是当访问网站时,页面长时间无响应,最后显示"504 Gateway Time-out"错误。

2. 问题排查

2.1 检查 Nginx 错误日志
首先,我检查了 Nginx 的错误日志,发现有大量类似下面的错误:

复制

2023/06/08 15:30:45 [error] 1234#1234: *1 upstream timed out (110: Connection timed out) while connecting to upstream, client: xxx.xxx.xxx.xxx, server: example.com, request: "GET /index.php HTTP/1.1", upstream: "fastcgi://unix:/run/php/php8.1-fpm.sock", host: "example.com"

这个错误表明,Nginx 在尝试连接 PHP-FPM 的过程中超时了。

2.2 检查 PHP-FPM 服务状态
接下来,我检查了 PHP-FPM 的状态,使用命令 sudo systemctl status php8.1-fpm,发现 PHP-FPM 服务是正常运行的。

2.3 检查 Nginx fastcgi 超时设置
然后,我怀疑可能是 Nginx 的 fastcgi 超时设置太短了。我检查了 Nginx 的配置文件 /etc/nginx/nginx.conf,发现 fastcgi 的超时设置如下:

复制

fastcgi_connect_timeout 60s;
fastcgi_send_timeout 60s;
fastcgi_read_timeout 60s;

这些设置看起来是合理的,60秒的超时时间对于大多数请求来说应该足够了。

2.4 检查 PHP-FPM 进程数设置
最后,我怀疑可能是 PHP-FPM 的进程数太少,导致请求排队,超过了 Nginx 的超时时间。我检查了 PHP-FPM 的配置文件 /etc/php/8.1/fpm/pool.d/www.conf,发现 PM 设置如下:

ini

复制

pm = dynamic
pm.max_children = 5
pm.start_servers = 2
pm.min_spare_servers = 1
pm.max_spare_servers = 3

这个设置表明,PHP-FPM 的进程数是动态调整的,最多可以有5个进程,起始有2个进程,最少有1个空闲进程,最多有3个空闲进程。

考虑到网站的访问量,这个设置的进程数可能有点少。

2.5 检查 Nginx 配置文件
在检查 Nginx 配置文件时,我发现在多个地方定义了 fastcgi_index 指令,导致 Nginx 报错,无法启动。

具体来说,fastcgi_index 指令同时出现在以下两个文件中:

  • /etc/nginx/snippets/fastcgi-php.conf
  • /etc/nginx/sites-available/wordpress.conf

3. 问题解决

3.1 解决重复的 fastcgi_index 指令
为了解决重复的 fastcgi_index 指令问题,我决定在网站的配置文件 /etc/nginx/sites-available/wordpress.conf 中保留 fastcgi_index 指令,然后从 /etc/nginx/snippets/fastcgi-php.conf 文件中删除 fastcgi_index 指令。

修改完成后,我运行 sudo nginx -t 测试 Nginx 配置,确保没有错误。然后我运行 sudo systemctl reload nginx 重新加载 Nginx 配置。

3.2 调整 PHP-FPM 进程数设置
为了解决 504 网关超时问题,我调整了 PHP-FPM 的 PM 设置,增加了进程数:

复制

pm.max_children = 20
pm.start_servers = 5
pm.min_spare_servers = 5
pm.max_spare_servers = 10

调整后,PHP-FPM 最多可以有20个进程,起始有5个进程,最少有5个空闲进程,最多有10个空闲进程。这个设置应该能够满足更高的并发请求。

保存配置文件后,我重启了 PHP-FPM 服务:

复制

sudo systemctl restart php8.1-fpm

然后我再次访问网站,这次网站成功加载,没有再出现504错误

4. 总结

造成 WordPress 出现 504 网关超时错误的原因可能有多种,在我这个案例中,主要原因是 PHP-FPM 的进程数设置太少,导致请求排队,超过了 Nginx 的 fastcgi 超时时间。此外,Nginx 配置文件中重复的 fastcgi_index 指令也导致了 Nginx 无法正常启动。

解决方法如下:

  1. 检查 Nginx 错误日志,定位问题
  2. 检查 PHP-FPM 服务状态
  3. 检查 Nginx fastcgi 超时设置
  4. 检查 PHP-FPM 进程数设置
  5. 检查 Nginx 配置文件,解决重复的 fastcgi_index 指令
  6. 调整 PHP-FPM 进程数设置,增加进程数
  7. 重启 PHP-FPM 服务,重新加载 Nginx 配置

在实际生产环境中,我们需要根据网站的访问量,合理设置 PHP-FPM 的进程数。同时也需要关注 Nginx 的 fastcgi 超时设置,确保其与 PHP-FPM 的处理能力相匹配。定期检查 Nginx 配置文件,避免出现重复的指令。

希望这篇文章对大家有所帮助。如果大家有任何问题或建议,欢迎在评论区交流。