Horizon 启动前必须确认 Redis 驱动已生效且连通,执行 migrate 建表,用 horizon 命令启动而非 queue:work,并配置好 Web 面板权限与 trim 策略。

Horizon 启动前必须确认 Redis 驱动已生效
Horizon 只支持 Redis 驱动,QUEUE_CONNECTION=redis 不只是写在 .env 里就完事。常见错误是配置了 redis,但 config/queue.php 中的 redis 连接块里 connection 指向了一个不存在的 Redis 配置名(比如写成 'connection' => 'cache',而 config/database.php 里根本没有叫 cache 的 Redis 配置)。
- 先验证 Redis 是否通:运行
php artisan tinker,然后输入Redis::ping(),返回"PONG"才算真正连上 - 检查
config/queue.php中redis连接的connection值,必须与config/database.php的redis.default或你自定义的键名完全一致 -
php artisan config:clear必须执行——改了.env或配置文件后不清理缓存,Horizon 会静默加载旧配置,报错却只显示 “Connection refused” 这类模糊信息
安装后要跑 migrate,不是 publish
很多人卡在 php artisan horizon:install 之后 Horizon 启不来,是因为只发布了配置没建表。horizon:install 做两件事:生成 config/horizon.php 和创建一个迁移文件,但迁移不会自动执行。
- 执行
php artisan migrate,它会建horizon_monitoring表(用于记录吞吐、延迟等指标)和failed_jobs表(如果还没建过) - 别漏掉
failed-table:如果之前用过database驱动,可能已有failed_jobs表,但 Horizon 默认依赖的是它自己的结构;建议统一用php artisan queue:failed-table+migrate重建 - 迁移失败常见原因是 MySQL 严格模式下
longtext字段没设默认值,可临时关 strict mode 或手动改迁移文件中$table->longText('exception')->nullable()
启动命令是 horizon,不是 queue:work
Horizon 是独立服务进程,它内部封装并接管了 queue:work,直接运行 php artisan queue:work 会绕过 Horizon 监控,所有指标、重试面板、任务追踪都失效。
- 正确启动方式只有:
php artisan horizon(开发环境)或php artisan horizon --daemon(生产环境推荐) - 别在 Supervisor 里配
queue:work再另起一个 Horizon 进程——它们会抢同一个 Redis 队列,导致任务重复消费或漏消费 - Horizon 默认监听所有队列(
*),如需限制,改config/horizon.php的environments→supervisor-*→queues数组,例如['emails', 'orders'] - 修改
config/horizon.php后必须重启 Horizon 进程,php artisan horizon:terminate是唯一安全重启方式,不能 kill -9
Web 面板打不开?检查中间件和路由暴露
Horizon Web 界面默认只在 local 环境启用,且依赖 App\Http\Middleware\AuthorizeHorizon 中间件控制访问权限。线上环境打不开,90% 是权限或路由没放开。
- 确保
APP_ENV=local或在config/horizon.php的use_https和middleware项显式配置允许的环境 - 检查
app/Providers/HorizonServiceProvider.php中Gate::define回调是否被覆盖或注释掉;默认只允许local和admin用户,普通用户进不去 - Horizon 路由挂载在
/horizon,如果用了 Nginx,确认没被location规则拦截(比如location ~ \.php$误匹配/horizon/xxx) - 打开面板后空白或 JS 报 404,大概率是
php artisan horizon:publish没运行(仅首次需要),或public/vendor/horizon目录权限不对
trim 配置(如 recent, failed, monitored)默认保留大量历史数据,不设上限会导致 Redis 内存持续上涨,最后 OOM。上线前务必根据业务量调整,而不是留着默认值。


















