horizon 是独立于 frankenphp 的 laravel 队列监控进程,需单独启动、守护并配置专用 redis 连接(名为 horizon),不可与 frankenphp 共容器或共 supervisor;其路由需手动启用,面板依赖正确 auth 授权和 horizon_enabled 环境变量。

Horizon 要跑在 PHP 进程里,不是 FrankenPHP 的一部分
FrankenPHP 管 HTTP 入口、静态文件、TLS 和 PHP 执行环境,但它不接管 Laravel 队列逻辑。Horizon 本质是 Laravel 的一个 Artisan 命令进程(php artisan horizon),必须单独启动、单独守护,和 FrankenPHP 是并列关系,不是子服务。
常见误解是以为配好 FrankenPHP 就能自动拉起 Horizon —— 实际上它完全没感知。你得像在 Nginx + PHP-FPM 环境里一样,为 Horizon 单独准备运行时、Redis 连通性、Supervisor 守护和权限策略。
- FrankenPHP 启动后监听
:80和:443,只处理 HTTP 请求;Horizon 默认监听 Redis 的horizon:*键,完全不走 HTTP 端口 - 两者共用同一份
.env和config/horizon.php,但进程隔离:FrankenPHP 是 Go 主进程,Horizon 是独立的 PHP CLI 进程 - 如果你用 Docker 部署,别把 Horizon 塞进同一个容器——它会和 FrankenPHP 抢 CPU、日志混乱、重启策略冲突;推荐拆成两个 service:一个
web(FrankenPHP),一个horizon(纯 PHP CLI)
Redis 连接必须双配置:FrankenPHP 用一套,Horizon 用另一套
Horizon 强制要求 Redis 驱动,且内部硬编码使用名为 horizon 的连接名(来自 config/database.php 的 redis.horizon)。而 FrankenPHP 自身不依赖这个连接名,它只管 PHP 运行时是否能执行 Redis::ping() —— 但 Horizon 启动失败时,报错往往藏在静默里,实际卡在连接名不匹配。
- 检查
config/database.php中是否存在'horizon' => [ 'host' => env('REDIS_HOST', '127.0.0.1'), ... ]块,不能只靠default或cache -
.env中要显式定义REDIS_HORIZON_HOST等变量,并在配置中引用,避免和主 Redis 连接混用 - 运行
php artisan tinker后执行config('database.redis.horizon.host')和Redis::connection('horizon')->ping(),两步都成功才算过关 - FrankenPHP 容器内若用
localhost指向 Redis,Horizon 容器必须用 Docker 网络别名(如redis),否则connection refused是常态
Supervisor 守护 Horizon 进程,别用 FrankenPHP 的 auto-restart
FrankenPHP 的 restart: always 只对它自己的 HTTP 服务生效,对 Horizon 进程零作用。Horizon 是常驻 CLI 进程,一旦崩溃或被 OOM kill,必须靠 Supervisor 拉起,否则面板白屏、快照停更、失败任务堆积。
- Supervisor 配置里 command 必须带
--daemon:php /app/artisan horizon --daemon,不加则进程启动即退出 - 不要在 Supervisor 里同时跑
queue:work和horizon—— 两者都会消费 Redis 队列,导致任务重复执行或漏执行 - Supervisor 的
autostart=true和autorestart=true必须启用,且startsecs=3(Horizon 启动较慢,设太短会被判失败) - 日志路径建议分开:
stdout_logfile=/var/log/horizon.log,别和 FrankenPHP 的 access/error 日志混在一起,排查时容易串行
Horizon 面板路由和权限必须手动放开,FrankenPHP 不自动注入
FrankenPHP 不修改 Laravel 的服务提供者加载顺序,也不干预 Route::middleware() 行为。Horizon 默认只在 APP_ENV=local 下注册路由,生产环境必须显式放行,否则 /horizon 永远 404。
- 确认
App\Providers\HorizonServiceProvider::class在config/app.php的providers数组中未被注释 - 在
AppServiceProvider::boot()里写授权回调:Horizon::auth(fn ($request) => $request->user()?->can('viewHorizon')),别用fn () => true上线 -
config/horizon.php中'enabled' => env('HORIZON_ENABLED', true),并在.env里设HORIZON_ENABLED=true - FrankenPHP 的
php_server指令只处理.php文件和 FastCGI 协议,Horizon 面板是 Laravel 的普通路由,只要 PHP 环境正常、路由注册成功,它就能响应 —— 不需要额外 Caddy 重写规则
--daemon 参数 —— 这两个点没踩准,整个监控就失效,但错误日志里往往只字不提。php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











