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

Linux环境下PHP服务内存占用过高问题及优化咨询

解决Docker部署的PHP服务内存占用过高且无法释放的问题

嘿,我来帮你搞定这个Docker里PHP服务内存飙到4GB还不自动释放的麻烦!先梳理下你的场景:你跑了个死循环的PHP脚本,每隔15秒执行一次数据处理、DB查询、API调用和日志写入,同时用Docker里的Supervisor管理cron服务。问题的核心在于这个长期常驻的PHP进程,加上脚本内可能存在未及时释放的资源,导致内存持续累积。下面给你按优先级排序的优化方案:

1. 优先重构:把常驻进程改成定时任务(最稳妥)

PHP的CLI模式天生适合一次性执行的脚本,进程结束后会自动释放所有内存,从根源上避免内存泄漏。你完全不需要让脚本一直跑,改成定时触发就行:

  • 先把脚本改成单次执行版本(去掉外层的while(1){ sleep(15); ... },只保留单次处理逻辑)
  • 用cron实现15秒间隔的触发:如果系统支持精细定时,或者写个小bash脚本配合cron:
    # 比如创建run_every_15s.sh
    #!/bin/bash
    for i in {1..4}; do
        php /path/to/your/script.php
        sleep 15
    done
    
    然后在cron里设置每分钟执行这个bash脚本:* * * * * /path/to/run_every_15s.sh,这样就能实现每15秒执行一次PHP脚本,每次执行完进程就退出,内存全释放。

2. 修复脚本内的内存泄漏(如果非要保留常驻进程)

如果业务场景必须让脚本常驻运行,那就要手动管理内存和资源:

  • 每次循环结束后,主动释放变量并触发垃圾回收:
    unset($data, $d); // 释放循环内的变量
    gc_collect_cycles(); // 强制触发PHP垃圾回收
    
  • 数据库操作:确保每次查询后关闭连接,比如用PDO的话,用完后设置$pdo = null;,不要用持久化连接(PDO::ATTR_PERSISTENT => false)
  • API调用:如果用curl,每次调用后必须关闭句柄:curl_close($ch);,避免句柄和内存泄漏
  • 日志写入:如果是手动打开文件句柄,写完后一定要fclose($fp);,不要长期保持文件打开状态

3. 给Docker设置内存限制(兜底方案)

不管怎么优化,都可以给Docker容器设置内存上限,防止它占用过多主机资源:

  • 在docker run命令里添加参数:--memory=1g --memory-swap=1g(限制容器最多用1GB内存,超过会触发OOM kill)
  • 如果用docker-compose,在服务配置里加:
    services:
      your-service:
        # ...其他配置
        deploy:
          resources:
            limits:
              memory: 1g
    
    配合Supervisor的自动重启配置,就算进程被OOM杀死,也能自动恢复。

4. 调整Supervisor配置(适配你的服务)

你的当前Supervisor配置是管理cron,但如果是直接运行常驻PHP脚本,应该把Supervisor指向PHP脚本本身:

[program:php-data-service]
command=php /path/to/your/script.php
autostart=true
autorestart=true
startretries=3
stdout_logfile=/var/log/php-service.log
stderr_logfile=/var/log/php-service.err.log
user=www-data
stopasgroup=true ; 确保停止进程时连带子进程一起关闭

这样Supervisor能直接监控PHP进程的状态,异常退出时自动重启。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.28 10:00:12