hyperf 定时任务子进程异常重启主因是配置错误、信号未拦截或资源泄漏,需从进程注册、信号捕获、动态重载三方面保障稳定:须显式注册至 processes.php;在 handle() 中注册 sigterm 处理并打标日志;通过 usr1 信号或 crontab:reload 命令实现热重载而非重启。

Hyperf 定时任务子进程(crontab-dispatcher)异常重启,往往不是“崩溃后自动拉起”,而是因配置、信号处理或资源问题导致进程被主动终止,再由主进程重新 fork。要稳定运行并可监听其状态变化,关键在于三方面:进程注册方式、信号拦截机制、以及配置变更的可观测性。
确认 crontab-dispatcher 进程是否被正确注册
该进程必须显式注册到 config/autoload/processes.php,否则不会启动,更谈不上监听:
- 检查文件中是否包含
\Hyperf\Crontab\Process\CrontabDispatcherProcess::class - 确保没有与其他自定义进程冲突(例如重复注册、命名冲突)
- 若使用了自定义进程基类或重写了
start()方法,需确认未屏蔽SIGTERM或USR2信号的默认处理逻辑
捕获 dispatcher 进程的退出信号与日志上下文
dispatcher 进程本身不直接执行任务,只负责分发;但它一旦异常退出,会导致整点/整分任务漏触发。建议在进程级加轻量监听:
- 在
CrontabDispatcherProcess的handle()方法开头加入pcntl_signal(SIGTERM, [$this, 'onStop']),并实现onStop()记录日志 + 清理 - 所有日志统一打上
process: crontab-dispatcher标签,便于 K8s 或日志系统过滤 - 避免在
handle()中做阻塞操作(如未设超时的 Redis 查询),否则会卡住调度循环,触发 Swoole 的max_request或心跳超时而被主进程 kill
动态配置变更时触发 dispatcher 重载(非重启)
如果定时任务规则存在数据库或配置中心动态管理,不要靠杀进程来生效——应让 dispatcher 主动感知变化并 reload 任务列表:
- 监听配置中心变更事件(如 Apollo 的
ConfigChangeEvent),在监听器中调用\Hyperf\Crontab\Strategy\ScanStrategy::reload() - 或在自定义命令中手动触发:
php bin/hyperf.php crontab:reload,该命令会向 dispatcher 进程发送USR1信号,触发内部 reload - 注意:reload 不等于重启进程,它只是清空内存中的任务缓存并重新扫描,对正在执行的任务无影响
排查高频异常重启的典型诱因
根据线上案例,以下情况最易导致 dispatcher 子进程反复退出:
- 内存溢出:任务类中存在静态变量累积、未释放的资源句柄(如 PDOStatement 未 close)、或大对象未 unset
- 协程泄漏:在定时任务回调中启动了协程但未 await 或未设置超时,导致协程长期挂起,占用内存和调度资源
-
配置加载失败:如
crontab.php中某条任务的callback类不存在,或构造函数抛异常,dispatcher 会在初始化阶段 panic 退出 -
时区/时间解析错误:cron 表达式含非法字符或时区未设(
timezone配置为空),可能导致解析器 panic











