跳转到主要内容
.
7 分钟阅读

解决 Cloudflare 522 超时错误:一次因 Apache MaxRequestWorkers 不足引发的深度排查

背景

生产环境中的 Debian 服务器(Apache 2.4.38 + MySQL)上运行着若干 WordPress 及自定义 PHP 应用。近期频繁出现 Cloudflare 522 错误(Connection timed out),但服务器 CPU、内存负载正常,Apache 和 MySQL 服务也都在运行。用户访问网站时随机出现无法打开的情况,影响了业务可用性。

什么是 522 错误?

522 是 Cloudflare 特有的错误码,表示 Cloudflare 边缘节点尝试与源服务器建立 TCP 连接后,在允许的时间内未收到完整的 HTTP 响应。Cloudflare 等待源服务器响应的时间大约为 19 秒(连接建立)到 90 秒(数据接收)。

关键认知:522 不代表服务器宕机或资源爆满,而是 源服务器未能及时响应。即使 CPU、内存看起来正常,仍然可能出现 522。

排查过程

1. 初步检查(排除常见原因)

  • 防火墙:iptables -L 无 DROP/REJECT 规则,Cloudflare IP 未被拦截。
  • MySQL:max_connections=151,当前连接数仅 10,无异常。
  • KeepAlive:已开启(KeepAlive On,超时 5 秒),配置合理。
  • 网络连接状态:ss -tan 显示 ESTAB 连接数高达 428,而 TIME-WAIT 仅 250+,未耗尽临时端口。
  • 系统日志:无 OOM、无内核错误。

表面上看一切“正常”,但 522 依然发生。

2. 关键发现:Apache 进程数远低于并发连接数

执行 ps aux | grep apache2 | wc -l 显示 Apache 进程数仅 152,而并发 ESTAB 连接数为 428
这意味着有大量 TCP 连接处于 ESTABLISHED 状态,但 Apache 没有足够的进程来同时处理它们。

3. 检查 Apache 并发限制(MPM prefork)

查看 MPM 配置 /etc/apache2/mods-available/mpm_prefork.conf

apache

code
<IfModule mpm_prefork_module>
    StartServers             5
    MinSpareServers          5
    MaxSpareServers         10
    MaxRequestWorkers       150      # 最大并发处理进程数
    MaxConnectionsPerChild   0
</IfModule>

MaxRequestWorkers 被设置为 150,意味着 Apache 最多只能同时处理 150 个请求。
当瞬时并发超过 150 时,新请求会进入排队队列;如果队列在 Cloudflare 超时时间内未能被处理,Cloudflare 就返回 522。

4. 更深层限制:ServerLimit 默认为 256

尝试直接提高 MaxRequestWorkers 到 384 后,执行 apache2ctl configtest 出现警告:

text

code
AH00180: WARNING: MaxRequestWorkers of 384 exceeds ServerLimit value of 256 servers,
decreasing MaxRequestWorkers to 256.

原来 Apache prefork 模式下还有一个 ServerLimit 指令,它定义了 MaxRequestWorkers 理论上限,默认值为 256。因此即使配置 384,实际生效的也只有 256。

5. 其他辅助问题

  • .htaccess 中存在语法错误:<RequireAll not allowed in <FilesMatch> context>,导致部分请求被拒绝。
  • 日志中出现 proxy:error (32)Broken pipe,表示反向代理连接中断(本环境未使用 PHP-FPM,该错误来自其他代理配置)。
  • 系统未配置 swap 分区,且存在 swap 设备挂载失败的错误,存在内存耗尽风险。

这些虽然不是 522 的根本原因,但会加重服务不稳定性,增加触发超时的概率。

解决方案

核心修复:调整 Apache MPM prefork 的 ServerLimit 和 MaxRequestWorkers

编辑 /etc/apache2/mods-available/mpm_prefork.conf

apache

code
<IfModule mpm_prefork_module>
    StartServers             5
    MinSpareServers          5
    MaxSpareServers         10
    ServerLimit            384          # 必须 >= MaxRequestWorkers
    MaxRequestWorkers      384
    MaxConnectionsPerChild   0
</IfModule>

注意

  • ServerLimit 必须出现在 MaxRequestWorkers 之前
  • 修改后需要重启 Apache 才能生效。
  • 根据服务器内存调整数值:prefork 模式下每个进程约消耗 30~50MB,384 个进程约需 12~19GB。本例服务器总内存 31GB,可用 16GB,设定 384 合理。

重启并验证:

bash

code
sudo systemctl restart apache2
ps aux | grep apache2 | wc -l          # 应接近 384
apache2ctl -S | grep MaxRequestWorkers # 确认生效

辅助优化

  1. 修复 .htaccess 语法错误
    将 <FilesMatch "\.php$"><RequireAll>...</RequireAll></FilesMatch> 改为 <FilesMatch "\.php$"> Require all granted </FilesMatch>
  2. 处理 proxy:error
    确认无反向代理需求后,禁用 mod_proxy 模块:bashsudo a2dismod proxy proxy_http sudo systemctl restart apache2
  3. 创建 swap 分区(避免内存不足):bashsudo fallocate -l 4G /swapfile sudo chmod 600 /swapfile sudo mkswap /swapfile sudo swapon /swapfile echo ‘/swapfile none swap sw 0 0’ | sudo tee -a /etc/fstab

效果验证

修改后,Apache 进程数从 150 提升至 384,能够匹配高峰期的 400+ 并发连接。监控显示:

  • ESTAB 连接数与 Apache 进程数基本持平。
  • 网站不再出现 Cloudflare 522 错误。
  • 用户访问恢复流畅,服务稳定。

经验总结

  1. 522 错误的首要排查方向是源服务器的请求处理能力,而非仅仅看 CPU/内存。
  2. Apache prefork MPM 下,MaxRequestWorkers 和 ServerLimit 是两个关键参数,后者常被忽略。修改时必须同时调整。
  3. 通过 ps 和 ss 对比进程数与 ESTAB 连接数,能快速判断是否达到并发上限。
  4. 不要忽视配置语法错误和 swap 缺失,它们会放大主问题的影响。
  5. Cloudflare 日志中的 ray_id 和源服务器错误日志结合分析,能精准定位超时发生的环节。

附录:常用排查命令

bash

code
# 查看 Apache 当前进程数
ps aux | grep apache2 | wc -l

# 查看 80 端口 ESTABLISHED 连接数
ss -tan state established sport = :80 | wc -l

# 查看 MPM 配置及生效值
apache2ctl -S | grep -i "maxrequestworkers"

# 测试配置文件语法
apache2ctl configtest

# 实时监控对比
watch -n 2 'echo "Procs: $(ps aux | grep apache2 | wc -l)"; echo "ESTAB: $(ss -tan state established sport = :80 | wc -l)"'

希望这篇文章能帮助遇到类似问题的同行快速定位并解决 Cloudflare 522 错误。

讨论 / DISCUSS

0
No Comments

还没有留言,来留下第一条评论吧!

留下足迹