You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

求助:Laravel在AWS ALB+Apache2环境下数据库连接无法正常关闭

Laravel应用MySQL连接堆积排查与解决

问题场景

部署架构:AWS EC2(Ubuntu 24.04)+ Apache2 + AWS ALB,后端为Laravel 10.48.28(PHP 8.2),数据库采用AWS RDS MySQL 8.0.39。核心问题为睡眠状态MySQL连接持续堆积,最终触发Too many connections错误导致服务中断。已完成基础排查:

  • Laravel数据库配置PDO::ATTR_PERSISTENT设为false
  • MySQL wait_timeout/interactive_timeout配置合理
  • Apache2 KeepAlive设为Off
  • ALB闲置超时设置正常

针对性排查与解决方案

1. 强制Laravel请求结束时回收数据库连接

部分场景下PHP请求生命周期的收尾钩子未正常触发,导致连接未释放。可在app/Providers/AppServiceProvider.php中手动注册请求终止事件:

use Illuminate\Support\Facades\DB;

public function boot()
{
    // 注册请求结束回调,强制断开所有数据库连接
    $this->app->terminating(function () {
        DB::disconnect();
    });
}

修改后执行php artisan optimize:clear生效。

2. 调整Apache MPM模式与进程配置

若当前使用prefork MPM(每个请求对应独立进程),易出现连接泄漏。建议切换为event MPM(线程化模式,资源复用更高效):

# 禁用prefork模块
sudo a2dismod mpm_prefork
# 启用event模块
sudo a2enmod mpm_event
# 重启Apache服务
sudo systemctl restart apache2

同时修改/etc/apache2/mods-available/mpm_event.conf的进程参数,避免进程长期存活导致连接泄漏:

<IfModule mpm_event_module>
    StartServers             2
    MinSpareThreads         25
    MaxSpareThreads         75
    ThreadLimit             64
    ThreadsPerChild         25
    MaxRequestWorkers      150
    # 进程处理1000个请求后自动重启,释放资源
    MaxConnectionsPerChild   1000
</IfModule>

修改后重启Apache生效。

3. 排查MySQL连接来源与进程状态

通过MySQL命令查看睡眠连接的详细信息,定位是否为特定进程持续持有连接:

SHOW PROCESSLIST;

重点关注Host(EC2实例IP)、Time(睡眠时长)、Id(进程ID),若发现同一进程ID长期处于睡眠状态,说明该进程内存在连接泄漏,需对应排查Apache/PHP进程的生命周期配置。

4. 调整PHP-FPM进程复用策略(若使用PHP-FPM)

若应用采用Apache + PHP-FPM架构,需限制FPM进程的请求处理次数,避免进程长期运行导致连接泄漏:
在PHP-FPM的池配置文件(如/etc/php/8.2/fpm/pool.d/www.conf)中修改:

# 每个进程处理500个请求后自动重启
pm.max_requests = 500

修改后重启PHP-FPM服务:

sudo systemctl restart php8.2-fpm

5. 检查Laravel队列/异步任务的连接释放

若应用使用Laravel队列,长期运行的Worker进程可能未正确释放连接。可通过两种方式处理:

  • 在任务类的handle方法末尾手动断开连接:
public function handle()
{
    // 任务业务逻辑
    DB::disconnect();
}
  • 启动队列Worker时设置超时参数,限制任务运行时长:
php artisan queue:work --timeout=60

6. 优化ALB健康检查路径

确保ALB的健康检查路径不会触发数据库连接(如使用静态页面/health,仅返回HTTP 200状态码),避免频繁的健康检查请求创建大量短期连接。

临时缓解方案

若需快速恢复服务,可临时调整RDS MySQL参数组中的max_connections值(如从默认151上调至300),但需注意RDS实例的内存容量,避免触发内存不足问题。此方案仅为临时措施,需配合上述排查找到根本原因。

内容的提问来源于stack exchange,提问作者Ravi Kyada

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.14 12:21:03