Hyperf定时任务灰度发布需避免kill-9,应通过SIGTERM触发平滑退出并设置stopTimeout≥最长任务执行时间,分批摘流量、等旧进程自然结束后再启新进程,配合分布式锁、状态记录与日志打标保障幂等与可追溯。

Hyperf 定时任务进程在灰度发布时,不能简单 kill -9 或直接重启,否则会导致定时任务漏执行、重复执行或状态丢失。关键在于让当前正在运行的定时任务自然结束,同时新版本进程只在灰度节点就绪后再接管调度。
确认定时任务运行模式
Hyperf 默认使用 TaskWorker 模式(基于 Swoole Task 进程)或独立的 Timer Worker 进程(如通过 php bin/hyperf.php start 启动的守护进程)。灰度重启前需明确:
- 是否启用
timer.enable_coroutine = true(协程定时器,更轻量但不跨进程) - 是否使用
Hyperf\Task\TaskExecutor或自定义的Timer管理器 - 定时任务是否依赖全局状态(如 Redis 锁、数据库标记),需确保新旧版本逻辑兼容
配置平滑退出信号与超时机制
在 config/autoload/processes.php 或启动配置中,为定时任务进程显式注册 SIGTERM 处理,并设置合理退出宽限期:
- 在进程启动时监听
SIGTERM,触发$this->stop()或手动清理逻辑 - 设置
stopTimeout≥ 最长单次定时任务执行时间(例如 30s),避免被强制 kill - 若使用
Hyperf\Process\ProcessManager,确保onStop回调中释放资源、等待活跃任务完成
灰度节点分批滚动重启
不要全量重启,而是按灰度批次控制:
- 先将目标节点从服务发现(如 Consul/Nacos)摘除流量,但保留定时任务进程继续运行
- 发送
SIGTERM给旧进程,等待其自然退出(可通过ps aux | grep hyperf观察进程数变化) - 确认旧进程完全退出后,再拉起新版本进程(建议加
--env=gray标识便于日志区分) - 验证新进程已注册定时任务(查看
hyperf:timer:list或日志中Timer started)
增强任务幂等与状态可追溯
即使做了平滑重启,仍需防御性设计:
- 每个定时任务开头加分布式锁(如 Redis lock + 唯一任务标识 + 过期时间)
- 记录任务执行状态到 DB/Redis(如
task:sync_user:20260813),避免重复触发 - 关键任务支持手动补偿(提供 CLI 命令如
php bin/hyperf.php task:retry --date=2026-08-13) - 日志打标:包含
version、pid、node_id,便于灰度期间快速定位异常
不复杂但容易忽略的是信号捕获和退出等待时间匹配——很多问题其实出在旧进程没真正停稳,新进程就抢着注册了相同定时器。


















