ThinkPHP 6 定时任务性能监控需围绕触发链路和执行过程主动埋点:触发层监控 cron 准时性与进程状态,命令层监控 execute() 耗时与内存峰值,队列层区分推送与消费延迟,聚合分析用轻量脚本与日志统计实现可观测性。

ThinkPHP 6 定时任务本身不内置性能监控能力,真正可落地的高阶监控,必须围绕“触发链路”和“执行过程”两个维度主动埋点、采集、聚合——不是靠框架自动上报,而是靠开发者在关键环节显式记录耗时、状态与上下文。
触发层监控:确保 cron 真正准时唤醒
系统级调度是否可靠,是性能监控的第一道防线。cron 自身不提供执行日志,需人工补全:
- 每条 crontab 条目必须重定向标准输出与错误流,例如:
0 2 * * * cd /var/www/app && /usr/bin/php think sync:order >> /var/log/cron/sync_order_$(date +\%Y\%m\%d).log 2>&1 - 日志开头统一打印时间戳与进程 PID:
echo "[`date '+%Y-%m-%d %H:%M:%S'`] PID: $$" >> /var/log/cron/xxx.log,用于识别是否重复启动或卡死 - 用
ps -eo pid,lstart,cmd | grep 'think sync:order'定期抽检,确认无残留僵尸进程;若发现多个同名进程并存,说明上一次未正常退出(如未 return 或被 kill -9)
命令层监控:量化 execute() 执行耗时与资源占用
CLI 环境下无法复用 Web 请求的 trace 日志通道,需手动打点:
- 在
execute()开头记录起始时间:$start = microtime(true); - 结尾计算并写入结构化日志:
Log::channel('cron')->info('sync:order', ['cost' => round(microtime(true) - $start, 3), 'mem_peak' => memory_get_peak_usage(true)]); - 避免使用
echo或$output->writeln()做性能判断依据——它们不反映真实业务逻辑耗时,且可能被缓冲影响测量精度 - 对数据库操作密集型任务,在关键 SQL 前后加微秒级计时,定位慢查询瓶颈(例如模型 save()、Db::table()->select())
队列层监控:区分调度延迟与执行延迟
当定时任务只负责推任务进队列(如 Queue::push('app\job\SendNoticeJob', $data)),真正的耗时发生在消费端,必须分开监控:
立即学习“PHP免费学习笔记(深入)”;
- 推送侧记录入队时间与 Redis zset score(延迟队列场景):
Log::channel('queue')->info('push_delay_job', ['at' => time(), 'delay' => 300, 'score' => time() + 300]); - 消费侧在
fire()开头打点,并在$job->delete()前记录总耗时;失败时用$job->fail()并记录错误类型(如 Redis 连接超时、HTTP 请求 timeout) - 通过 Redis CLI 快速检查队列积压:
redis-cli -a yourpass llen queues:notice和zcard queues:notice_delay,数值持续增长即预警 - 监听
queue:failed事件,将失败任务写入专用表(如queue_failed_logs),字段含 job_id、exception、failed_at、attempts
聚合分析:用轻量工具实现可观测性
无需引入 Prometheus + Grafana 复杂栈,用已有能力即可构建有效视图:
- 每日凌晨用 shell 脚本解析昨日 cron 日志,提取平均耗时、最长单次耗时、失败次数,生成简报邮件
- 在 ThinkPHP 后台管理页嵌入「定时任务健康看板」:读取
runtime/log/cron/下最近 7 天日志文件,统计各命令成功/失败率、P95 耗时趋势 - 对关键任务(如订单同步、库存校验)设置硬性 SLA:例如「单次执行 ≤ 8 秒,失败率
- 禁用所有未配置监控的日志通道(如默认的 file 驱动),防止因磁盘满导致任务静默失败



















