Horizon面板需同时满足Redis连通性、定时快照、权限放行、独立进程四条件,缺一即导致白屏、吞吐冻结或失败任务不显示;路由未注册或权限过严致404/白屏,生产环境须手动启用;吞吐图表异常因horizon:snapshot未定时执行;失败任务不可见因未被队列捕获或Redis存储配置不当。

Horizon 面板不是装完就能用的,它必须和 Redis 连通性、定时快照、权限放行、独立进程四者同时就位,缺一不可——否则白屏、吞吐冻结、失败任务不显示都是常态。
为什么 /horizon 页面 404 或白屏?
最常见原因是路由未注册或权限拦截过严。Horizon 默认只在 APP_ENV=local 下自动注册路由,生产环境必须手动放开。
- 检查
config/horizon.php中enabled是否为true(设成false会静默禁用全部功能) - 确认
App\Providers\HorizonServiceProvider::class在config/app.php的providers数组中且未被注释 - 在
AppServiceProvider::boot()中临时加一句:Horizon::auth(fn ($request) => true);(上线前替换为真实鉴权逻辑) - 新版 Horizon(v5.10+)推荐用
php artisan horizon:install初始化,它会自动创建配置、迁移、软链接资源,比vendor:publish更可靠
吞吐量图表不动或延迟严重?
吞吐量、延迟、活跃任务数等指标全靠 horizon:snapshot 命令定时采集并写入 Redis 和数据库,这个命令默认由 Laravel Scheduler 每分钟执行一次。没配调度,数据就永远停在初始状态。
- 在
app/Console/Kernel.php的schedule()方法中加入:$schedule->command('horizon:snapshot')->everyMinute(); - 确认服务器 cron 正确指向:
* * * * * cd /path/to/project && php artisan schedule:run >> /dev/null 2>&1 - 手动运行
php artisan horizon:snapshot观察输出——如果报 Redis 连接超时或权限拒绝,说明底层连接异常;该命令失败时通常静默,不会抛错 - 注意:
APP_ENV=testing下 Horizon 会跳过所有快照收集,测试时切到local或production
失败任务看不到、重试无效或堆栈为空?
Horizon 展示失败任务的前提是:任务确实被 Laravel 队列系统捕获并存入 horizon:failed(Redis)或 failed_jobs(database),而不是直接崩溃退出。
- Laravel 用 Redis 驱动时,失败任务默认存进 Redis 的
horizon:failed列表,不是failed_jobs表——所以不要指望php artisan queue:failed能列出 Horizon 管理的失败任务 - 检查
config/queue.php中failed配置项是否启用;Redis 驱动下需确保redis连接可用且未被限流 - 如果任务里用了
try/catch吞掉了异常,且没主动throw,Horizon 就不会把它当失败 - 重试操作本质是把失败任务从
horizon:failed移回对应队列(如redis:queues:default),若重试后仍失败,说明业务逻辑本身有异常,和 Horizon 无关
真正容易被忽略的是:Horizon 的监控数据不是“实时”的,而是依赖 horizon:snapshot 的采样节奏 + Redis 状态同步 + Web 界面拉取三者协同。哪怕页面看着在动,背后某个环节卡住,指标就会失真——别只信 UI 数字,关键时候得直查 redis-cli LLEN queues:high 或看 ps aux | grep horizon:work。


















