优雅关闭laravel高优先级队列进程需避免强制终止:一、用queue:restart触发平滑退出;二、发送sigterm信号等待任务完成;三、通过supervisor可控停机;四、改用queue:listen自然终止;五、自定义中间件拦截新任务。

如果您正在运行 Laravel 高优先级队列进程(如监听 high 队列),需在不中断当前任务执行的前提下终止其消费行为,则必须避免直接 kill 进程或强制终止 worker。以下是实现优雅关闭的多种方法:
一、使用 queue:restart 命令触发平滑退出
该命令向缓存写入重启信号,所有以 --daemon 模式运行的 queue:work 进程会在完成当前正在处理的任务后主动退出,从而实现无损关闭。
1、确认高优队列进程正以 daemon 模式运行:php artisan queue:work redis --queue=high --daemon --sleep=3 --tries=3。
2、执行重启信号写入:php artisan queue:restart。
3、验证信号是否生效:进入 php artisan tinker 后运行 Cache::get('laravel_queue_restart_signal'),返回非空时间戳即表示信号已写入。
4、注意:若使用 database 作为缓存驱动,信号无法跨进程共享;必须使用 redis 或 file 驱动。
二、发送 SIGTERM 信号并等待任务完成
Linux 系统级信号可被 Laravel worker 捕获,worker 在收到 SIGTERM 后将停止拉取新任务,并仅等待当前任务结束即退出,符合优雅语义。
1、查出正在运行的 high 队列进程 PID:ps aux | grep 'queue:work.*high' | grep -v grep | awk '{print $2}'。
2、向该 PID 发送终止信号:kill -TERM {PID}。
3、观察进程是否自动退出:ps aux | grep {PID},若无输出则表示已成功退出。
4、关键约束:必须确保进程未以 --once 模式启动,否则无法响应 SIGTERM。
三、结合 Supervisor 执行可控停机流程
Supervisor 可接管信号传递与生命周期管理,通过配置 stopwaitsecs 参数保障 worker 有足够时间完成当前任务,避免硬杀导致任务丢失或重复。
1、在 Supervisor 配置中为 high 队列 worker 设置:stopwaitsecs=45,确保宽限期覆盖最长任务执行时间。
2、启用组管理机制:killasgroup=true 和 stopasgroup=true,防止子进程残留。
3、执行安全停机指令:supervisorctl stop laravel-high-worker。
4、验证进程状态:supervisorctl status laravel-high-worker,应显示 STOPPED 而非 FATAL。
四、利用 queue:listen 模式实现自然终止
queue:listen 启动的是短生命周期进程,每次仅消费单个任务后即退出,天然支持“无状态关闭”——只需终止当前进程,下一轮不会自动重建,无需额外信号干预。
1、将 high 队列 worker 切换为 listen 模式:php artisan queue:listen redis --queue=high --sleep=5000 --timeout=60。
2、确认 Redis 已启用键空间通知:notify-keyspace-events Ex,保障事件驱动唤醒可靠性。
3、手动终止当前 listen 进程:pkill -f 'queue:listen.*high'。
4、注意:此模式下不可依赖 --max-jobs,因每次执行即退出,--max-jobs 无效。
五、通过自定义中间件拦截新任务注入
在不终止进程的前提下,阻止 high 队列接收新任务,使其自然消耗完积压后静默退出,适用于灰度下线或维护窗口场景。
1、创建中间件 BlockHighQueueMiddleware,在 handle() 中检查全局开关:if (Cache::has('block_high_queue')) { throw new \Exception('High queue is disabled'); }。
2、为 high 队列 worker 启动时注册该中间件:php artisan queue:work redis --queue=high --middleware=BlockHighQueueMiddleware。
3、启用拦截开关:Cache::put('block_high_queue', true, 3600)。
4、关键效果:已入队任务仍会执行,但新任务将立即失败并进入 failed_jobs 表,便于后续审计。











