关于批次队列Bus 的回调函数callback 内部调用$this 指向内存泄漏的问题[已踩坑]
Laravel: 8.x
PHP: 7.3
OS: MAC
我现在有 job1 和job-batch 队列若干
job1有问题代码:
Bus::batch($jobs)
// 所有任务完成才执行的回调
->finally(function (Batch $batch) {
if ($batch->finished()) {
dispatch(new BeforeLoanExportFinishJob($this->task->id));
}
})->dispatch();
job1正常代码:
$taskId = $this->task->id;
Bus::batch($jobs)
// 所有任务完成才执行的回调
->finally(function (Batch $batch) use ($taskId) {
if ($batch->finished()) {
dispatch(new BeforeLoanExportFinishJob($taskId));
}
})->dispatch();
报错:
直接是 500 Server error ,502 bad way ,前面是服务器错误,后者大概率是内存过大,超时
根本原因来自 批次队列的 finally 回调内部调用了 $this
造成了内部循环引用,内存无法释放,这个位置大家一定要避坑,很难调试
下面放上这个issue地址:
Referencing $this within batch callback depletes memory
job1 使用了外部传入对象
/**
* Create a new job instance.
*
* @return void
*/
public function __construct(Task $task)
{
//
$this->task = $task;
}
job1 内有调用了batch 队列, 再使用batch 队列回调的时候, 内部调用了this ,结果就是把外层的队列给序列化,提示的错误是pdo 无法支持序列化,就是因为再batch 的回调内使用了this
finally 回调里面如果是闭包,执行的是序列化的操作,会导致序列化失败
local.ERROR: You cannot serialize or unserialize PDO instances {"exception":"[object] (PDOException(code: 0): You cannot serialize or unserialize PDO instances at /Users/raybon/TaiFinance/www/download-center/vendor/opis/closure/src/SerializableClosure.php:155)
[stacktrace]
使用批次队列正确的方式:
后面使用过程中,切记 this 直接调用,会造成内存泄漏
8.x 版本 还没文档提示
9.x 版本已经更新了提示:
[9.x] Add note to ‘Chain Failures’ and ‘Queueing Closures’ section to not use ‘$this’ in callbacks
本作品采用《CC 协议》,转载必须注明作者和本文链接
mark