定时任务
功能简介
框架内置秒级定时任务调度器。写一个控制器方法、在配置文件里登记一次,调度器就会按设定的频率自动执行,不需要依赖系统的 crontab,也不用装额外的消息队列组件。
支持的能力:
- 秒级调度:最小频率 1 秒,适合需要高频执行的业务
- 并发处理:单个任务可以开多个并行实例分片处理数据,开箱即用
- 多节点协调:多机部署时,多个节点可以竞争执行(只有一个跑)、或各自独立执行,由运行模式决定
- 后台可视化管理:查看任务列表、动态调整并发、手动触发任务、启停任务、查看每次执行的日志
后台提供了两个管理页面:
| 页面 | 路径 | 作用 |
|---|---|---|
| 定时器配置 | 系统管理 → 定时器配置 | 管理任务:调并发、手动触发、启停、切换运行模式 |
| 定时器日志 | 系统管理 → 定时器日志 | 查看每次执行的记录:状态、耗时、错误信息、返回结果 |
添加一个定时任务
分两步:写任务控制器、注册任务配置。
第一步:编写任务控制器
在 app/tools/controller/timer/ 下创建控制器,继承 app 层的 TimerController 入口类,实现 do() 方法:
<?php
namespace app\tools\controller\timer;
use app\common\controller\TimerController;
class SyncOrder extends TimerController
{
public function do()
{
$count = OrderService::syncFromExternal();
return "同步了 {$count} 条订单";
}
}
要点:
- 只实现
do()方法,不要重写execute()(框架自动调用并记录执行日志) do()抛出的异常会自动捕获并记录为失败- 返回值会记录到执行日志的结果字段
第二步:注册任务配置
在 app/common/command/timer/config.php 创建配置文件(首次使用时创建):
<?php
return [
[
'name' => 'sync_order',
'type' => 'site',
'target' => '/tools/timer.SyncOrder/execute',
'frequency' => 60,
'concurrency' => 1,
],
];
字段说明:
| 字段 | 说明 |
|---|---|
name |
任务唯一标识,不能重复 |
type |
固定填 site(通过 HTTP 调用控制器) |
target |
任务控制器的 URL 路径,格式 /tools/timer.控制器名/execute |
frequency |
执行频率,单位秒。填 60 表示每 60 秒执行一次 |
concurrency |
并发数量,默认 1。需要并行处理时增大此值,开箱即用,无需引入额外组件 |
框架自带的任务(日志清理等)配置在
extend/base/common/command/timer/config.php。你的自定义任务写在app/common/command/timer/config.php,两个文件的配置会自动合并。
并发处理(可选)
并发默认就支持,不需要切换模式或引入消息队列等组件。配置文件填 concurrency 即可,同时控制器里设置相同的 $concurrency 属性作为安全上限:
class SyncOrder extends TimerController
{
protected $concurrency = 3; // 和配置文件保持一致
public function do()
{
// 按 concurrencyId 分片处理不同数据
$offset = $this->concurrencyId * 100;
$orders = Order::where('status', 0)->limit(100)->skip($offset)->select();
// ...
}
}
concurrency=3 时框架自动创建 3 个并行实例(编号 0/1/2),通过 $this->concurrencyId 区分各自处理哪部分数据。后台还能动态调整并发数,实时生效不用重启。
启动定时器
手动启动
# 常规启动
php think timer
# 本地开发(请求打到本地 web 服务)
php think timer --local
# 临时跑一轮(验证任务是否正常,跑完自动退出)
php think timer --local --temp
Docker 模式
使用框架内置 Docker 部署时(docker compose up 或 docker run ... server),定时器随容器自动启动,无需手动运行。
后台管理
定时器配置
路径:系统管理 → 定时器配置
任务列表展示所有已注册的定时任务,以及每个任务的运行类型、状态、并发数、最后执行节点和时间:

调整并发
点击任务的"编辑"按钮,修改并发数。提供两种模式:
- 默认(继承代码):使用配置文件里写的并发数,数据库留空
- 自定义:填正整数覆盖代码默认值

切换到"自定义"后,输入框激活,填入想要的并发数即可:

保存后实时生效,定时器进程无需重启。规则:空值=继承代码默认;正整数=覆盖;0 或负数会被拒绝(防止静默吞掉任务)。
手动触发
手动触发用于调试或立即执行某个任务,不受频率限制。操作前必须先选择目标节点:
页面左上角有"节点视角"下拉框,默认是"全局配置(不选节点)"。点击展开后会列出当前所有在线节点(标注主节点):

选中某个节点后,表格操作列会多出一个"触发"按钮(未选节点时不显示):

点击"触发",任务立即在选中节点执行一次,执行结果会记录到定时器日志。手动触发会穿透停用状态——即停用的任务也能手动触发一次用于调试。
启用/停用
状态列的开关。停用后任务不再自动执行,但手动触发仍然有效。
运行模式
| 模式 | 行为 | 什么时候选 |
|---|---|---|
| 竞争执行(默认) | 多节点部署时只有一个节点执行 | 绝大多数任务用这个 |
| 仅主节点 | 只有主节点执行 | 需要集中处理的任务 |
| 所有节点 | 每个节点各自独立执行 | 清理本机缓存等每个节点都要跑的任务 |
| 仅手动 | 永不自动执行,只靠手动触发 | 临时性、按需执行的任务 |
定时器日志
路径:系统管理 → 定时器日志
每次任务执行都会自动记录一条日志,包括任务名称、执行节点、开始/结束时间、耗时、状态、错误信息:

通过日志可以判断任务是否正常:
- 状态列:成功显示绿色,失败显示红色
- 错误信息列:失败时会显示异常信息,成功时为"-"
- 节点ID列:显示这次是哪个节点执行的,多节点部署时可以据此判断任务是否按预期调度(例如竞争模式下应该看到不同节点轮流执行)
- 耗时列:单次执行用时,判断是否有性能问题
点击每行的"详情"可以查看完整信息,包括 do() 方法的返回结果。
原文标题:内置定时器
原文文档:ulthon_admin
原文地址:/read/augushong/ulthon_admin/zh-cn/2.x/61a5d47e8743c/6a6581d502ebf.html
原文平台:奥宏文档