在上一篇文章中,我们通过 PHP‑CLI常驻进程内存泄漏快照定位实战,定位并修复了支付回调场景下 queue:work 常驻进程内存泄漏导致的 OOM 故障。

内存泄漏解决之后,新的运维问题随之而来:如何提前发现队列消费堆积、进程静默僵死、大量任务失败,而不是等到用户反馈订单回调超时、对账异常才紧急处理?

很多线上事故并不是一瞬间爆发,而是队列持续堆积数小时无人感知。尤其支付业务,回调延迟、重复消费、任务丢失都会直接影响订单状态和资金对账,一套完整的Laravel队列监控体系是生产环境必备基础设施。

Laravel队列常见线上故障:堆积、僵死、任务丢失

大部分开发者只依赖 Supervisor 托管队列进程,认为配置 autorestart 就足够保障可用性,这是生产环境非常典型的误区。

Supervisor 只能监控进程是否存活,无法识别「进程正常运行,但不再消费任务」的静默僵死问题。

结合支付回调、订单通知这类业务场景,队列线上故障分为三类:

1. 消费堆积:入队速率大于消费速率,待处理任务持续上涨,回调延迟不断增加;

2. 进程僵死:queue:work 进程存在、PID正常,卡在第三方HTTP请求、数据库锁、死循环,不再拉取新任务;

3. 批量任务失败:第三方网关超时、数据库异常,大量Job进入failed_jobs表,需要人工重试。

常规日志排查效率很低,等到翻日志定位问题,往往已经产生业务影响。监控建设的核心目标:采集关键指标、设置阈值告警,将故障发现前置。

Supervisor守护 queue:work 基础配置与避坑

Supervisor 作为进程托管工具,是整个队列体系的底层保障。很多网上示例配置缺少内存安全回收参数,长期运行依然会出现内存持续上涨,和我们 PHP‑CLI常驻进程内存泄漏快照定位实战 中分析的泄漏案例相互呼应。

Ubuntu 系统安装 Supervisor:

sudo apt update
sudo apt install supervisor -y

新增队列配置文件 /etc/supervisor/conf.d/laravel-worker.conf

[program:laravel-worker]
process_name=%(program_name)s_%(process_num)02d
command=php /www/laravel/artisan queue:work redis --queue=pay_callback --sleep=3 --tries=3 --max-jobs=500 --max-time=3600
autostart=true
autorestart=true
user=www-data
numprocs=2
redirect_stderr=true
stdout_logfile=/var/log/laravel-worker.log
stopwaitsecs=3600

重点参数说明,支付业务队列建议严格遵守:

--max-jobs:单个Worker最多处理500个任务后优雅退出,避免内存缓慢累积;

--max-time:最长运行一小时强制重启,规避静默僵死;

--tries=3:任务最多重试3次,防止异常任务无限重试占用资源;

stopwaitsecs 设置足够超时时间,避免强制杀死正在执行的支付回调任务,引发重复处理。

配置生效命令:

sudo supervisorctl reread
sudo supervisorctl update
sudo supervisorctl restart laravel-worker:*

常见避坑点:代码发布之后,必须重启Worker,否则老进程运行旧业务代码;日志目录需要赋予www-data读写权限,避免日志写入失败掩盖故障信息。

自建指标监控:队列长度、进程状态、失败任务统计

Laravel 队列监控体系整体架构
Laravel队列监控架构,Supervisor进程托管、Redis任务队列、指标采集与告警通知完整流程

监控体系分为两条路线:轻量自建指标(中小项目无需引入重型组件)、Laravel Horizon 官方监控面板(Redis驱动推荐)。

优先介绍轻量化自建方案,无需额外中间件依赖,适合支付业务小型服务快速落地。

我们可以编写自定义Artisan命令,定时采集队列待消费数量、failed任务总数、运行Worker进程数量,写入日志或推送监控平台。

简易队列状态采集示例代码:

<?php

namespace App\Console\Commands;

use Illuminate\Console\Command;
use Illuminate\Support\Facades\Redis;

class QueueMonitor extends Command
{
    protected $signature = 'queue:monitor-status';
    protected $description = '采集队列监控指标';

    public function handle()
    {
        $queueName = 'pay_callback';
        $pending = Redis::llen("queues:$queueName");
        $failedCount = \DB::table('failed_jobs')->count();

        $this->info("pending_jobs: {$pending}");
        $this->info("failed_jobs: {$failedCount}");
    }
}

然后在 app/Console/Kernel.php 设置定时执行,每5分钟采集一次指标:

$schedule->command('queue:monitor-status')
    ->everyFiveMinutes()
    ->withoutOverlapping();

采集的核心指标清单(支付队列重点观测):

1. 待处理任务数量:持续上涨判定消费堆积;

2. 失败任务总数:短时间突增代表依赖服务异常;

3. 活跃Worker进程数:低于预期代表进程大面积退出;

4. 任务平均等待时长:回调类任务等待过长会影响订单同步。

如果项目使用Redis驱动队列,推荐接入 Laravel Horizon,官方原生支持指标采集、等待超时通知、可视化面板。

composer require laravel/horizon
php artisan horizon:install
php artisan migrate

配置 config/horizon.php 可以针对支付回调独立队列设置等待告警阈值,当任务等待超过指定时间自动触发通知。

配置告警:及时发现消费堆积与进程异常

采集指标之后,告警规则是监控闭环最重要一环。只存储指标不配置告警,无法实现故障提前发现。

中小项目可以基于定时采集命令增加阈值判断,对接钉钉、企业微信机器人推送告警消息,无需部署Prometheus、Grafana等重型监控组件。

简易告警逻辑示例:当pay_callback队列待处理任务超过200条,推送告警通知,提示队列堆积。

支付业务告警优先级建议:

一级告警(紧急,需要立刻处理):支付回调队列大量堆积、连续大量任务失败、所有Worker进程退出;

二级告警(观测跟进):任务平均等待时间缓慢上涨、失败任务小幅增加。

同时建议把 PHP‑CLI常驻进程内存泄漏快照定位实战 提到的 RSS 内存指标一并纳入监控,实现内存爬坡提前告警,避免再次出现OOM被内核杀死的故障。

Failed Job 管理:任务重试、清理与根因排查

支付场景下,进入失败任务表的大多是第三方支付网关回调、通知推送、对账同步任务,不能直接批量全部重试,容易造成重复回调、重复通知,引发资产业务风险。

基础常用命令:

# 查看所有失败任务
php artisan queue:failed

# 根据uuid重试单条失败任务(支付业务优先单条重试,核对业务数据)
php artisan queue:retry 任务uuid

# 删除指定失败任务
php artisan queue:forget 任务uuid

运维规范建议:

1. 禁止线上随意执行 queue:retry all 批量重试全部失败任务;

2. 失败任务保留周期建议7~15天,定时清理老旧无效数据,防止 failed_jobs 数据表持续膨胀;

3. 每个支付Job内部做好幂等控制,和我们之前静态数组去重方案配套使用,多重保障防止重复消费。

线上运维最佳实践

整套Laravel队列监控落地之后,结合支付业务长期运维经验,整理几条可长期执行的最佳实践:

1. 队列资源隔离:支付回调等高优先级任务单独队列、独立Worker进程,避免报表导出、消息推送等重型任务抢占资源;

2. 分层监控:底层Supervisor托管进程、中间层采集队列指标、业务层监控订单回调完成率,多层防护;

3. 定期巡检:每周查看失败任务报表,复盘高频报错Job,优化第三方超时、数据库锁等底层问题;

4. 发布流程规范:代码上线完成后,必须平滑重启队列Worker,避免新旧代码混合运行引发未知异常;

5. 内存长期观测:持续采集Worker RSS内存指标,及时发现缓慢内存泄漏,杜绝凌晨OOM故障复现。

队列监控不是一次性搭建完成就永久稳定,需要跟随业务流量迭代调整告警阈值、Worker进程数量。对于支付系统而言,队列承载着订单回调、对账同步等核心链路,完善的监控告警体系,是保障资金链路稳定、降低夜间应急故障的核心手段。