Laravel队列需优雅重启以确保代码更新生效:一、用queue:restart命令触发信号,进程完成当前任务后退出;二、结合Supervisor自动拉起新进程;三、无Supervisor时用Cron轮询信号;四、多服务器用Redis Pub/Sub广播;五、改用--once模式短周期执行。

当Laravel应用通过队列处理异步任务时,若代码更新后队列工作进程仍运行旧版本逻辑,将导致任务执行异常或数据不一致。为确保新代码立即生效且不中断正在处理的任务,需实施优雅重启策略。以下是多种可落地的配置与操作方法:
一、使用 queue:restart 命令触发优雅重启
该命令向 Laravel 队列系统写入一个时间戳信号,所有正在运行的 queue:work 进程在完成当前任务后检查该信号,确认存在即自动退出,由进程管理器(如 Supervisor)拉起新进程加载最新代码。
1、确保队列工作进程以 --daemon 模式运行(Laravel 8+ 默认启用),例如:php artisan queue:work redis --sleep=3 --tries=3。
2、在部署脚本末尾执行:php artisan queue:restart。
3、验证信号是否写入:运行 php artisan tinker 后输入 Cache::get('laravel_queue_restart_signal'),返回时间戳即表示信号已生效。
4、注意:若使用 database 驱动,需确保 cache 驱动非 array,否则信号无法跨进程共享;推荐使用 redis 或 file 缓存驱动。
二、结合 Supervisor 实现自动拉起与平滑切换
Supervisor 不仅监控进程存活,还可配合 queue:restart 完成“先发信号、再回收、后重建”的闭环,避免手动干预遗漏。
1、在 Supervisor 配置文件中设置 autostart=true、autorestart=true 和 startsecs=5。
2、添加 stopwaitsecs=30,确保工作进程有足够时间完成当前任务并响应重启信号。
3、配置 killasgroup=true 和 stopasgroup=true,防止子进程残留。
4、部署后执行 supervisorctl reread && supervisorctl update,再执行 php artisan queue:restart;此时 Supervisor 将在检测到进程退出后立即启动新实例。
三、使用 Cron 定期轮询重启信号(无 Supervisor 环境)
在无法部署 Supervisor 的轻量环境(如部分 Plesk 或共享主机),可通过系统 Cron 每分钟检查重启信号并主动终止旧进程,实现类优雅效果。
1、编写 shell 脚本 /usr/local/bin/laravel-queue-watch.sh,内容包含:if php artisan tinker --execute="echo Cache::has('laravel_queue_restart_signal') ? '1' : '0';" | grep -q '1'; then pkill -f 'queue:work'; fi。
Laravel Cloud(cloud.laravel.com)。此技能用于处理所有 Laravel Cloud 请求,包括搜索和读取数据。只要任务涉及 Laravel Cloud,即使用此技能。
2、赋予执行权限:chmod +x /usr/local/bin/laravel-queue-watch.sh。
3、添加系统级 Cron:* * * * * /usr/local/bin/laravel-queue-watch.sh。
4、每次部署仍需调用 php artisan queue:restart;该机制依赖进程名匹配,务必确保无其他 PHP 进程含 'queue:work' 字符串。
四、基于 Redis Pub/Sub 的分布式重启广播
在多服务器部署场景下,单点执行 queue:restart 仅影响本机进程。通过 Redis 发布订阅机制,可向全部节点广播重启指令,实现集群级同步。
1、修改队列启动命令,加入监听逻辑:在 queue:work 前插入自定义监听脚本,订阅频道 laravel:queue:restart。
2、使用 Redis::subscribe(['laravel:queue:restart'], function ($message) { exit(0); }); 在工作进程启动时注册退出钩子。
3、部署脚本中执行:redis-cli publish laravel:queue:restart "now"。
4、各节点监听到消息后立即退出当前任务;需确保所有队列进程均使用同一 Redis 实例且未启用数据库隔离。
五、禁用守护进程模式 + 短生命周期 Worker
放弃长时守护进程,改用短周期单次执行模式,从根本上规避代码热更新问题。虽牺牲少量性能,但稳定性与可预测性极高。
1、停止使用 queue:work --daemon,改用 queue:work --once 启动方式。
2、通过 Supervisor 或 systemd 配置循环执行:设置 command=php /var/www/artisan queue:work redis --once --sleep=3 --tries=3 并启用 autorestart=true。
3、每次任务执行完毕即退出,下次调度时自动加载全新代码;此方式无需任何 restart 命令,部署后下一次任务触发即生效。










