On this page
Cron
Cron 任务是按定义的时间表自动运行的计划任务。您可以通过 Deno.cron() API 在代码中定义 cron 任务,部署您的应用,平台会发现并按计划运行它们。
在代码中定义 cron 任务 Jump to heading
Deno.cron() 接受一个可读性强的名称、一个时间表和一个处理函数。名称用于在仪表盘和日志中标识该 cron 任务,时间表决定它何时触发,处理函数包含每次调用时要执行的代码。时间表可以是标准的五字段 cron 表达式或结构化对象。所有时间均为 UTC — 这避免了夏令时转换时的歧义。详情请参阅完整 API 参考。
Deno.cron("cleanup-old-data", "0 * * * *", () => {
console.log("清理旧数据...");
});
Deno.cron(
"sync-data",
"*/15 * * * *",
{
backoffSchedule: [1000, 5000, 10000],
},
async () => {
await syncExternalData();
},
);
常见的时间表表达式 Jump to heading
| 时间表 | 表达式 |
|---|---|
| 每分钟 | * * * * * |
| 每 15 分钟 | */15 * * * * |
| 每小时 | 0 * * * * |
| 每 3 小时 | 0 */3 * * * |
| 每天凌晨 1 点 | 0 1 * * * |
| 每周三午夜 | 0 0 * * WED |
| 每月第一天午夜 | 0 0 1 * * |
组织 cron 声明 Jump to heading
您必须在模块顶层注册 cron 任务,且要在 Deno.serve() 启动之前。平台通过评估模块顶层代码在部署时提取 Deno.cron() 定义 — 这就是它发现有哪些 cron 任务存在及其时间表的方式。在请求处理器内、条件语句中或服务器启动之后注册的 cron 任务将不会被识别。
随着 cron 任务数量的增长,全部放在主入口文件可能会显得杂乱。常见做法是将 cron 处理器定义在专门的文件中,并在入口文件顶部进行导入。
Deno.cron("cleanup-old-data", "0 * * * *", async () => {
await deleteExpiredRecords();
});
Deno.cron("sync-data", "*/15 * * * *", async () => {
await syncExternalData();
});
import "./crons.ts";
Deno.serve(handler);
由于 Deno.cron() 调用在模块顶层执行,仅导入该模块即可注册 cron 任务,无需调用或重新导出任何内容。
对于有大量 cron 任务的项目,可以使用 crons/ 目录,里面每个文件对应一个 cron 任务或一组相关任务,并使用一个中枢文件重新导出它们:
import "./cleanup.ts";
import "./sync.ts";
import "./crons/mod.ts";
Deno.serve(handler);
限制 Jump to heading
定义 cron 任务时需注意一些限制。传递给 Deno.cron() 的名称最长不能超过 256 字符 — 这是出现在仪表盘和日志中的标识符,因此保持简洁是个好习惯。免费组织中,每个修订版本最多注册 10 个 cron 任务。如果项目需要更多,可以升级至付费计划以解除限制。
执行生命周期与状态 Jump to heading
当 cron 任务到期时,会在它被注册的每个时间线独立触发。每次执行运行该时间线活动修订版中的处理函数。例如,如果 cleanup-old-data 任务分别在生产时间线和 staging 分支时间线上注册,生产时间线的执行会运行生产修订版的处理函数,staging 时间线的执行会运行 staging 修订版的处理函数。每次执行会计为一次入站 HTTP 请求。
Cron 任务执行的状态包括:
| 状态 | 颜色 | 描述 |
|---|---|---|
| 运行中 | 黄色 | Cron 任务处理函数正在执行 |
| 成功 | 绿色 | 执行成功 |
| 错误 | 红色 | 失败 — 悬停查看错误信息 |
平台防止重复执行:同一 cron 任务不能并发运行。如果上一次执行仍在运行,下一次预定触发将被跳过。这样避免了资源争用,确保每次执行能顺利完成。
重试与退避 Jump to heading
默认情况下,失败的 cron 任务不会重试。您可以选择提供 backoffSchedule 数组来启用重试并精确控制每次重试的时间。
backoffSchedule 是一个延迟毫秒数数组,每个元素指定下一次重试前等待的时间:
- 每次执行最多 5 次重试
- 每次重试的最长延迟:1 小时(3,600,000 毫秒)
- 重试不会影响 cron 任务的计划 — 下一次预定运行仍按时执行,即使先前运行的重试仍挂起。如果重试与下一次预定运行时间重叠,后者将按照上面所述的重叠策略跳过。
示例:backoffSchedule: [1000, 5000, 10000] 表示重试最多 3 次,间隔分别为 1 秒、5 秒和 10 秒。
仪表盘 Jump to heading
应用侧栏的 Cron 标签页为您提供项目中所有注册 cron 任务的概览。每条记录显示 cron 任务的时间表、最近执行情况和其所属的活动时间线。当同名的 cron 任务在不同时间线以不同时间表注册时,每个不同时间表都会作为独立条目显示,方便您分别跟踪。
点击任意 cron 任务的“查看详情”可打开详情页,显示完整的执行历史。您可通过搜索栏筛选执行记录:
status:<值>— 按状态筛选 (ok,error,running)timeline:<名称>— 按时间线名称筛选(子串匹配,大小写不敏感)
可观测性集成 Jump to heading
Cron 任务执行会产生 OpenTelemetry 跟踪。点击执行历史中的“查看跟踪”进入该特定跟踪的 可观测性 跟踪页面。
在跟踪页面,您可以使用这些与 cron 相关的过滤条件:
kind:cron— 仅显示 cron spancron.name:<名称>— 按 cron 名称过滤cron.schedule:<时间表>— 按时间表表达式过滤
时间线 Jump to heading
Cron 任务会在生产和 git 分支的
时间线上运行。平台在部署时提取 Deno.cron() 定义并调度执行,因此每个时间线运行其活动修订版代码中定义的 cron 任务。要添加、删除或修改 cron 任务,请更新代码并部署新修订版。回滚到先前部署时会重新注册该部署中的 cron 任务。您可以在仪表盘对应时间线页面查看当前注册的 cron 任务。