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

Debian9下Apache2与PHP7内存泄漏问题求助

遇到这种Apache+PHP内存持续飙升最后爆内存的问题,我之前在生产环境碰过好几次,咱们先一步步排查原因,再对应解决:

排查内存泄漏的根源

1. 区分是PHP脚本还是Apache本身的问题

  • 先跟踪Apache子进程的内存变化:用ps aux | grep apache2查看每个子进程的RSS(常驻内存)数值,每次运行脚本后对比同一个进程的内存变化。如果某个进程的内存只增不减,那大概率是PHP脚本/扩展的内存泄漏;如果是Apache父进程内存持续上涨,那可能是Apache模块的问题。
  • 给PHP加内存监控:在脚本的关键节点(比如循环前后、大计算逻辑结束后)加入echo memory_get_usage(true);,打印当前内存占用,定位到哪段代码导致内存飙升不释放。测试环境还可以用valgrind --leak-check=full php your_script.php直接检测PHP脚本的内存泄漏,但注意别在生产环境跑这个,会拖慢运行速度。

2. 检查Apache MPM配置(Debian默认用prefork)

  • 打开/etc/apache2/mods-available/mpm_prefork.conf,看MaxRequestPerChild值:如果是0(默认),意味着子进程会一直运行,内存泄漏会持续累积。这是很常见的坑。
  • 同时检查MaxRequestWorkers(原MaxClients)、MinSpareServers这些参数:如果设置得过大,会导致同时运行太多Apache子进程,直接吃光内存。

3. 排查PHP扩展与脚本逻辑

  • 禁用非必要的PHP扩展:有些第三方扩展(比如老旧的图像处理、数据库扩展)存在内存泄漏问题。可以先在php.ini里注释掉可疑扩展,重启Apache后测试内存是否还增长,逐个排查。
  • 检查脚本中的循环引用:PHP7的垃圾回收器虽然改进了,但对象之间的循环引用(比如A对象引用B,B又引用A)可能导致内存无法自动释放。可以在循环结束后用unset()手动销毁变量,或者调用gc_collect_cycles()强制触发垃圾回收。
  • 检查资源是否未释放:比如打开大文件后没调用fclose(),数据库结果集没手动释放,或者使用了大量临时数组却没及时清理,这些都会导致内存占用居高不下。

针对性解决办法

1. 调整Apache MPM参数缓解内存累积

  • 修改mpm_prefork.conf中的MaxRequestPerChild为500-1000(根据你的请求量调整):让每个Apache子进程处理指定数量的请求后自动重启,避免内存泄漏持续累积。
  • 合理设置MaxRequestWorkers:根据服务器总内存计算,比如每个Apache子进程大概占200MB,8GB内存的话设成30左右,避免同时运行太多进程耗尽内存。修改后记得重启Apache:systemctl restart apache2。

2. 优化PHP脚本与配置

  • 开启并配置OPcache:在php.ini中确保zend_extension=opcache.so,设置opcache.enable=1、opcache.memory_consumption=128、opcache.max_accelerated_files=10000。OPcache会缓存编译后的PHP代码,减少重复编译的内存开销,同时也能避免一些编译阶段的内存泄漏。
  • 手动清理内存:在脚本的大计算、循环逻辑结束后,用unset()释放不再需要的变量、数组或对象,必要时调用gc_collect_cycles()强制回收垃圾内存。
  • 分批处理大任务:如果脚本要处理大量数据,别一次性把所有数据加载到内存,改成分批读取、分批计算,处理完一批就清理一批数据。

3. 切换到PHP-FPM(更稳定的进程管理)

如果mod_php的内存泄漏问题始终无法解决,建议切换到PHP-FPM,把PHP进程和Apache进程分开管理:

  • 安装对应版本的PHP-FPM:apt install php7.x-fpm(把7.x换成你的PHP版本,比如7.4)
  • 禁用mod_php:a2dismod php7.x
  • 启用Apache的proxy_fcgi和setenvif模块:a2enmod proxy_fcgi setenvif
  • 配置虚拟主机:在你的Apache虚拟主机配置中添加ProxyPassMatch ^/(.*\.php(/.*)?)$ unix:/run/php/php7.x-fpm.sock|fcgi://localhost/var/www/html/(替换/var/www/html/为你的网站根目录)
  • 重启服务:systemctl restart apache2 php7.x-fpm
  • 然后在PHP-FPM的配置文件/etc/php/7.x/fpm/pool.d/www.conf中设置pm.max_requests=1000,让每个FPM进程处理1000次请求后重启,从根源缓解内存泄漏。

4. 系统层面补充内存缓冲

  • 检查swap空间:用free -h查看swap使用情况,如果物理内存不足,swap可以临时缓解。如果swap不够,新增swap文件:
    fallocate -l 4G /swapfile
    chmod 600 /swapfile
    mkswap /swapfile
    swapon /swapfile
    
    然后把/swapfile none swap sw 0 0添加到/etc/fstab中,让swap永久生效。

内容的提问来源于stack exchange,提问作者Flash Thunder

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.19 07:24:16