Laravel邮件队列运行至3.8k任务后无异常停止问题求助
Laravel队列负责将邮件推送至SendGrid,队列中共15000个任务,但运行至约3800个时便自行停止,无任何错误或警告提示,仿佛任务已全部执行完毕,仅遗留1个失败任务。
代码实现如下:
$message = (new SongChallengeEmail( $this->getUsername($emailRawData->name, $emailRawData->username, $emailRawData->email), $emailRawData->email, $emailRawData->artists )) ->onConnection('database') ->onQueue('emails'); Mail::queue($message);
已尝试调高PHP内存限制(分别设置--memory=8000和-d memory_limit=1G),但问题依旧。目前考虑部署supervisor,但希望先明确问题根源。
以下是几个常见的排查方向和解决办法:
查看失败任务详情
执行命令查看失败任务的完整异常信息:php artisan queue:failed再通过任务ID查看具体栈追踪:
php artisan queue:failed {taskId}这个失败任务可能触发了未被捕获的致命异常,直接导致队列进程终止,而非正常退出。
调整队列超时与任务重启机制
Laravel队列默认单个任务超时时间为60秒,若邮件发送任务耗时超过这个时间,进程会被强制终止。可以延长超时时间,同时设置进程处理一定数量任务后自动重启(避免内存泄露):php artisan queue:work database --queue=emails --memory=8000 --timeout=300 --max-jobs=1000--max-jobs=1000让进程每处理1000个任务就自动重启,能有效避免内存积累导致的进程崩溃。检查数据库连接配置
使用database队列驱动时,若MySQL的wait_timeout或interactive_timeout设置过短,大量任务处理过程中可能出现数据库连接断开,导致队列无法获取后续任务。可以查看数据库的超时配置,或者在队列命令中添加--sleep=2参数,减少连接频繁切换的压力。排查SendGrid发送限制
登录SendGrid后台查看发送统计,确认是否触发了发送频率上限或配额限制。如果SendGrid返回了限流错误,而任务中未捕获该异常,可能导致队列进程异常终止。建议在邮件任务类中添加异常捕获,将错误日志写入Laravel日志:public function handle() { try { // 邮件发送逻辑 Mail::send(...); } catch (\Exception $e) { \Log::error('SendGrid发送失败: ' . $e->getMessage(), ['trace' => $e->getTraceAsString()]); throw $e; // 重新抛出异常让队列标记任务失败 } }查看系统与Laravel日志
检查Laravel的storage/logs/laravel.log,以及服务器的系统日志(如/var/log/syslog、/var/log/php-fpm.log),这些日志中可能记录了控制台未输出的致命错误、内存耗尽提示等隐藏问题。启用supervisor辅助排查
即使暂时不想长期用supervisor,也可以先配置它来管理队列进程。supervisor会在进程意外终止时自动重启,同时可以记录进程的输出日志,方便排查为什么进程会突然停止。配置示例:[program:laravel-queue] process_name=%(program_name)s_%(process_num)02d command=php /path/to/your/project/artisan queue:work database --queue=emails --memory=8000 --timeout=300 --max-jobs=1000 autostart=true autorestart=true user=your-user numprocs=2 redirect_stderr=true stdout_logfile=/path/to/your/project/storage/logs/queue.log
内容的提问来源于stack exchange,提问作者Emanuele Sacco

