hyperf 定时任务无内置进程超时销毁机制,需分场景实现:场景一用 hyperf-alarm-clock 在 crontab 方法内设协程超时;场景二通过协程 waittimeout + task 异步投递控制任务超时;场景三靠 task_max_request 限制 task 进程生命周期。

Hyperf 定时任务本身(通过 hyperf/crontab)不提供“进程超时自动销毁”机制,因为 Crontab 任务默认在主 Worker 进程或独立的 CrontabDispatcherProcess 中以协程方式执行,并非长期运行的子进程。所谓“超时销毁”,实际涉及的是两类常见场景:
- 定时任务方法内执行耗时操作,需主动中断或防卡死
- 投递到 Task 进程的异步任务,需设置执行超时与失败重试
下面分场景给出可落地的配置与代码方案:
✅ 场景一:Crontab 任务中防止单次执行卡死(推荐用 hyperf-alarm-clock)
适用于:数据库慢查询、HTTP 请求无响应、循环逻辑失控等。
// 在定时任务方法内启用超时保护
use Pudongping\AlarmClock\AlarmClock;
public function execute()
{
// 设置 30 秒超时,超时后抛出异常并触发通知(按配置)
AlarmClock::timeout(30, function () {
// 你的业务逻辑,例如:
$data = $this->userService->syncAllUsers();
$this->logger->info('Sync completed', ['count' => count($data)]);
});
}
? 前提:已安装并配置 hyperf-alarm-clock
配置示例(config/autoload/hyperf_alarm_clock.php):
return [
'enable' => (bool) env('ALARM_CLOCK_ENABLE', true),
'timeout' => 30, // 默认超时秒数
'channel' => ['console'], // 或 'feishu', 'dingtalk' 等
];
✅ 场景二:Task 进程任务超时控制(靠 task_worker_num + 协程超时)
Hyperf 的 Task 进程本身不支持单任务级超时销毁,但可通过以下组合实现“软性超时兜底”:
- 投递时加协程超时控制
- Task 方法内主动使用
Co::sleep()/Coroutine::waitTimeout() - 配合
task_enable_coroutine => true和非阻塞调用
// 在 Controller 或 Service 中投递带超时保障的 Task
$taskId = \Hyperf\Utils\Coroutine::create(function () {
try {
// 设置最大等待 60 秒,超时则取消
$result = \Hyperf\Utils\Coroutine::waitTimeout(60.0, function () {
// 真正的任务逻辑(必须是协程安全的)
Co::sleep(0.1);
return \Hyperf\Task\TaskExecutor::exec(
App\Task\HeavyTask::class,
'handle',
['param' => 'value']
);
});
if ($result === false) {
$this->logger->warning('Task execution timed out');
}
} catch (\Throwable $e) {
$this->logger->error('Task error', ['msg' => $e->getMessage()]);
}
});
⚠️ 注意:
TaskExecutor::exec()是同步阻塞调用,不推荐直接用;更合理做法是封装为@Async方法或使用Task组件的defer()+wait()模式。
✅ 场景三:强制限制 Task 进程生命周期(系统层兜底)
虽然不能“单个任务超时销毁”,但可限制整个 Task Worker 进程运行时长,避免内存泄漏累积:
// config/autoload/server.php
return [
'settings' => [
// Task Worker 最大执行时间(秒),超时后进程自动重启
'task_max_request' => 1000, // 每个 Task Worker 最多处理 1000 个任务后退出
'task_worker_num' => 4, // 根据 worker_num 合理设置(如 8 → 4~8)
'task_enable_coroutine' => true,
],
];
搭配监控项(关键!):
-
task_wait_queue_len:持续 > 0 表示积压,需扩容或优化任务 -
/dev/shm空间:task_tmpdir默认在此,空间不足会导致序列化失败静默丢任务
❌ 不可行的做法(避坑提醒)
- 试图用
set_time_limit()或pcntl_alarm()控制 Crontab 任务:无效,Swoole 协程下不生效 - 在
@Crontab方法里exit()或die():会终止当前协程,但可能影响调度器稳定性,禁止使用 - 依赖 Linux
ulimit -t限制 PHP 进程 CPU 时间:对协程无效,且影响全局
不复杂但容易忽略:超时不是加个 sleep() 就行,关键是协程上下文 + 非阻塞 I/O + 显式 timeout 控制。真正健壮的定时任务,得从任务设计、投递方式、执行环境三层一起约束。











