Hyperf定时任务通过CrontabManager在Worker协程中调度,需用Supervisor守护主进程、Redis分布式锁+singleton防重复、心跳上报实现容错。

Hyperf定时任务本身不依赖独立主进程,而是由框架内置的 CrontabManager 在主 Worker 进程中协程调度执行。所谓“主进程异常兜底重启”,实际是指当定时任务所在进程(如 crontab-dispatcher 或 Worker)因 OOM、崩溃、卡死等异常退出后,如何确保任务调度不中断、能自动恢复。
这不是靠 Supervisor 管理一个单独的“定时任务进程”,而是要让整个 Hyperf 服务具备进程级容错 + 任务级防丢失双重保障。
✅ 确保 Crontab 调度器随主服务稳定运行
Hyperf 的定时任务调度器(CrontabManager)默认集成在主 Server 生命周期中,启动时自动注册。它本身不单独 fork 进程,而是由一个常驻协程(通常在首个 Worker 中)持续轮询执行。
- 启动时会打印:
[INFO] Crontab manager started with X tasks - 若该 Worker 崩溃或被 kill,调度协程随之终止 → 任务停止执行
→ 所以首要前提是保证主 Worker 进程不轻易退出
建议配置:
// config/autoload/server.php
return [
'settings' => [
// 防止因单个请求/定时任务异常导致 worker 退出
'max_request' => 0, // 不限制单 worker 处理请求数
'reload_async' => true, // 异步重载,减少阻塞
'daemonize' => false, // 开发环境关 daemonize,便于观察日志
],
];✅ Supervisor 兜底:监控并重启整个 Hyperf 服务
Supervisor 不是用来管“定时任务进程”,而是守护 php bin/hyperf.php start 主进程。一旦主进程异常退出(比如 OOM 后 worker 全挂),Supervisor 可立即拉起新实例。
关键配置项(/etc/supervisord.d/hyperf.ini):
[program:hyperf] directory = /servers/app/myproject/ command = /servers/php/bin/php ./bin/hyperf.php start user = www-data autostart = true autorestart = true startsecs = 3 startretries = 3 stopasgroup = true killasgroup = true redirect_stderr = true stdout_logfile = /servers/app/myproject/runtime/stdout.log stderr_logfile = /servers/app/myproject/runtime/stderr.log
⚠️ 注意:
-
autorestart = true是核心,确保进程退出后自动重启; -
startsecs = 3表示进程启动后稳定运行满 3 秒才视为成功,避免闪退误判; -
stopasgroup+killasgroup防止子进程残留(如 crontab-dispatcher、consumer 等);
✅ 定时任务自身防单点失败:启用 Redis 分布式锁 + 单例模式
即使主进程重启,也要防止任务重复执行或漏执行。Hyperf 提供原生支持:
<?php
use Hyperf\Crontab\Annotation\Crontab;
#[Crontab]
class RefreshCacheCrontab extends AbstractCrontab
{
public string $name = 'refresh_cache';
public string $rule = '*/5 * * * *'; // 每5分钟
public array $singleton = true; // 同一时刻只允许一个实例运行
public array $mutex = ['type' => 'redis']; // 基于 Redis 实现跨进程互斥
public function execute(): void
{
// 业务逻辑,即使进程重启,锁也能保证不重复触发
cache()->set('last_cron_run', date('Y-m-d H:i:s'), 300);
}
}✅ 效果:
- 进程崩溃重启后,新实例仍能通过 Redis 锁判断上一次是否已执行;
- 配合
singleton = true,避免多 Worker 同时跑同一任务;
✅ 补充:主动探测 + 告警(可选但推荐)
在定时任务中加入心跳上报或状态标记,配合外部监控(如 Prometheus + AlertManager):
public function execute(): void
{
// 上报执行时间戳到 Redis 或 DB
redis()->setex('cron:refresh_cache:last_run', 3600, time());
// 执行业务...
}再用脚本/巡检服务定期检查 cron:refresh_cache:last_run 是否超时(如 > 10 分钟未更新),触发告警或人工干预。
不复杂但容易忽略:定时任务的健壮性,不在“怎么写逻辑”,而在“怎么扛住进程崩溃、网络抖动、锁失效”。把 Supervisor 守护、Redis 锁、singleton、日志追踪四者配齐,就能覆盖绝大多数生产异常场景。


















