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

Laravel Horizon worker内存溢出,如何在任务结束后清理实体释放内存?

Laravel Horizon Worker 内存泄漏解决方案

Horizon 作为常驻进程执行任务时,Laravel 框架自身的 Eloquent 缓存、服务容器单例、全局状态日志都会在多次任务执行后累积残留对象,由于存在隐式引用链路,PHP 自带的 GC 无法自动完成回收,最终导致内存溢出崩溃。以下是不同层级的解决方案:

1. 任务执行后主动重置状态(可达到接近初始化的内存占用)

在单个任务的 handle() 方法末尾执行以下操作:

  • 主动触发PHP循环引用回收:执行 gc_collect_cycles(),手动调用可以绕过 PHP GC 根缓冲区阈值限制,立刻回收所有无引用的对象
  • 重置数据库连接与Eloquent缓存:执行 \DB::purge('mysql')(将参数替换为你实际使用的数据库连接名),会断开旧连接、清空Eloquent内部全局缓存、关联关系残留、查询日志
  • 清理自定义单例实例:如果你的项目在服务容器中绑定了自定义单例,调用 app()->forgetInstance('你的服务别名') 清除已实例化的对象,可提前维护需要重置的单例列表批量操作
  • 手动切断大对象引用:将任务执行过程中创建的大Collection、模型实例、批量处理对象主动赋值为 null,切断引用链路方便回收

2. 配置进程自动重启(生产环境首选兜底方案)

无需修改业务代码,直接调整 Horizon 配置即可实现进程执行指定数量任务后自动退出,由 Master 进程重新拉起全新的干净进程,新进程的内存状态完全等同于应用初始化状态:

  • 打开 config/horizon.php,在对应环境的配置块中添加 'max_jobs' => 100,代表每个 Worker 进程执行完100个任务后自动退出

该方案是生产环境最高效、最稳定的兜底方案,进程重启的开销可以忽略不计,能解决90%以上的常驻进程内存泄漏问题

3. 禁用不必要的全局缓存

  • 任务执行前调用 \DB::disableQueryLog() 禁用SQL查询日志,避免大量查询日志堆积占用内存
  • 如果你在项目中使用了模型静态缓存、全局作用域静态属性、自定义全局缓存,任务结束后手动清空对应静态变量

4. 大数量查询优化

处理大量实体时不要用 get() 全量加载到内存,改用 chunk() 分块处理或者 cursor() 游标逐行处理,减少内存中同时存活的模型对象数量。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.14 03:00:02