Skip to main content
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 处理器定义在专门的文件中,并在入口文件顶部进行导入。

crons.ts
Deno.cron("cleanup-old-data", "0 * * * *", async () => {
  await deleteExpiredRecords();
});

Deno.cron("sync-data", "*/15 * * * *", async () => {
  await syncExternalData();
});
main.ts
import "./crons.ts";

Deno.serve(handler);

由于 Deno.cron() 调用在模块顶层执行,仅导入该模块即可注册 cron 任务,无需调用或重新导出任何内容。

对于有大量 cron 任务的项目,可以使用 crons/ 目录,里面每个文件对应一个 cron 任务或一组相关任务,并使用一个中枢文件重新导出它们:

crons/mod.ts
import "./cleanup.ts";
import "./sync.ts";
main.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 span
  • cron.name:<名称> — 按 cron 名称过滤
  • cron.schedule:<时间表> — 按时间表表达式过滤

时间线 Jump to heading

Cron 任务会在生产和 git 分支的 时间线上运行。平台在部署时提取 Deno.cron() 定义并调度执行,因此每个时间线运行其活动修订版代码中定义的 cron 任务。要添加、删除或修改 cron 任务,请更新代码并部署新修订版。回滚到先前部署时会重新注册该部署中的 cron 任务。您可以在仪表盘对应时间线页面查看当前注册的 cron 任务。

你找到了你需要的东西吗?

编辑此页面
隐私政策