使用supervisord配置Laravel Horizon时,单个Supervisor无法生成多Worker及任务数据不显示的问题
我刚帮几个开发者处理过类似的Horizon配置坑,咱们一步步来解决你的两个问题:
问题1:让单个Horizon Supervisor生成多个Worker
你当前的Supervisor配置启动了2个独立的Horizon进程,这会导致每个Horizon进程对应一个独立的Supervisor实例,各自管理自己的1个Worker,完全达不到你想要的“单个Supervisor下多Worker+负载均衡”的效果。正确的思路是让Supervisor只启动1个Horizon主进程,由Horizon自身来管理多个Worker进程。
修复步骤:
修改Supervisor配置文件 (
scheduler.conf)
把numprocs=2改成numprocs=1,因为Horizon会根据自身配置自动生成Worker,不需要Supervisor启动多个Horizon实例:[program:horizon] process_name=%(program_name)s command=php /www/E3/artisan horizon autostart=true autorestart=true user=web numprocs=1 redirect_stderr=true stdout_logfile=/var/log/supervisor/horizon.log stopwaitsecs=3600(注意:
process_name也可以简化,因为现在只有1个进程了)确认Horizon配置的有效性
你当前的config/horizon.php配置是正确的:balance=auto会根据队列负载自动调整Worker数量processes=2和minProcesses=2保证至少有2个WorkermaxProcesses=10(staging环境是3)限制最大Worker数
要确保你当前运行的环境和配置匹配:比如如果是staging环境,要确认
APP_ENV=staging,这样Horizon会加载staging环境的maxProcesses配置。重启服务生效
先停掉所有现有Horizon进程,再重启Supervisor:# 停止所有Horizon进程 sudo supervisorctl stop horizon:* # 重新读取Supervisor配置 sudo supervisorctl reread # 更新配置 sudo supervisorctl update # 启动Horizon sudo supervisorctl start horizon验证结果
运行php artisan horizon:status,你应该能看到supervisor-1下面列出多个Worker进程,且Horizon仪表盘的“Processes”区域会显示正确的Worker数量和负载均衡状态。
问题2:恢复Horizon任务详情的显示
Horizon的任务列表只返回计数、不显示具体任务数据,通常和任务存储的Redis连接、配置缓存或版本兼容性有关,按以下步骤排查:
排查步骤:
检查Redis连接与存储
Horizon默认使用Redis存储任务详情,确保:config/database.php中的Redis配置正确,尤其是horizon连接(如果单独配置了的话),能正常连接到Redis服务- 用
redis-cli执行KEYS horizon:*,查看是否存在horizon:completed_jobs、horizon:pending_jobs等键,且这些键有数据 - 检查Horizon配置中是否设置了过短的任务保留时间:比如
trim选项(默认是保留7天),如果被改成了0或者极短时间,任务详情会被自动清理,只剩下计数
清理配置缓存
缓存的配置可能导致Horizon无法读取最新的存储设置,执行以下命令:php artisan config:clear php artisan cache:clear php artisan horizon:publish验证版本兼容性
Laravel 8对应的Horizon版本应该是v5.x,检查composer.json中的laravel/horizon版本:"laravel/horizon": "^5.0"如果版本不匹配(比如装了v6.x),会出现兼容性问题,执行
composer require laravel/horizon:^5.0来降级到兼容版本。检查任务序列化方式
虽然可能性较低,但如果队列的序列化方式被修改为json,某些复杂任务的详情可能无法正常存储。确认config/queue.php中默认队列的serializer设置:'default' => [ 'driver' => 'redis', 'serializer' => 'php', // 保持默认的php序列化 // ...其他配置 ],重启Horizon
完成以上操作后,重启Horizon进程:sudo supervisorctl restart horizon此时再访问
/horizon/api/jobs/completed?starting_at=-1&limit=50,应该能看到包含任务详情的jobs数组了。
内容的提问来源于stack exchange,提问作者Adam Hopkinson

