调度流程运行#

Prefect允许你指定流程的运行调度。 你可以为任何已服务或已部署的流程添加一个或多个调度。 调度告诉 Prefect 何时以及如何创建新的流程运行。 你可以在 Prefect UI 中、通过 CLI 使用 prefect deployment schedule 命令,或者在 prefect.yaml 配置文件中给已部署的流程添加调度。

创建时间表#

有几种方式可以为部署创建时间表:

  • 通过 Prefect UI

  • 如果使用 serve 方法构建部署,则可以通过 cronintervalrrule 参数来创建 Flow 对象或serve工具以同时管理多个流程

  • 如果使用基于工作者的部署

    • 当你用 flow.serveflow.deploy 定义部署时

    • 通过交互式 prefect deploy命令

    • prefect.yaml 文件的 deployments -> schedules部分

在 UI 中创建调度#

你可以在UI中的部署页面的调度部分添加调度。 要添加时间表,请选择 + Schedule 按钮。 选择 间隔Cron 来创建调度。

关于RRule?

UI不支持创建RRule时间表。 然而,UI将显示你通过命令行创建的RRule时间表。

新创建的时间表将出现在你创建它的部署页面上。 新的计划流程运行可以在部署页面的即将到来选项卡中看到。

要编辑现有时间表,请从部署页面上的时间表旁边的三点菜单中选择编辑

使用 Python 创建调度#

在 Python 文件中,通过 flow.serve()serveflow.deploy()deploy 创建部署时,可以指定调度。只需添加关键字参数 cronintervalrrule 即可。

参数

描述

interval

执行部署的时间间隔。接受一个数字或timedelta对象来创建一个单一计划。如果给定一个数字,则解释为秒。也接受一个数字或timedelta的可迭代对象来创建多个计划。

cron

一个cron计划字符串,用于指定何时运行此部署的运行。还接受一个cron计划字符串的可迭代对象来创建多个计划。

rrule

一个rrule计划字符串,用于指定何时运行此部署的运行。还接受一个rrule计划字符串的可迭代对象来创建多个计划。

schedules

定义何时运行此部署的计划对象列表。用于定义多个计划或额外的调度选项,如timezone

schedule

定义何时运行此部署的计划对象。用于定义额外的调度选项,如timezone

下面 serve 方法将创建名为 my_flow 的部署,并使用 cron 计划每分钟创建一次运行:

from prefect import flow

from myproject.flows import my_flow

my_flow.serve(name="flowing", cron="* * * * *")

如果采用基于工作池的部署方式,deploy 方法具有相同的基于调度的参数。

my_flow 按照此 interval 调度运行时,它将从 2026 年 1 月 1 日午夜开始,在 America/Chicago 时区每10分钟运行一次。

from datetime import timedelta, datetime
from prefect.client.schemas.schedules import IntervalSchedule

from myproject.flows import my_flow

my_flow.serve(
  name="flowing",
  schedules=[
    IntervalSchedule(
      interval=timedelta(minutes=10),
      anchor_date=datetime(2026, 1, 1, 0, 0),
      timezone="America/Chicago"
    )
  ]
)

在终端中创建调度#

您可以通过交互式的 prefect deploy 命令来创建调度。系统会提示您选择要创建的调度类型。

在 YAML 中创建调度#

如果你保存了 prefect deploy 命令生成的 prefect.yaml 文件,你会发现它包含用于部署的 schedules 部分。 或者,你也可以根据配方或从头开始创建 prefect.yaml 文件,并向其中添加 schedules 部分。

deployments:
  ...
  schedules:
    - cron: "0 0 * * *"
      timezone: "America/Chicago"
      active: false
    - cron: "0 12 * * *"
      timezone: "America/New_York"
      active: true
    - cron: "0 18 * * *"
      timezone: "Europe/London"
      active: true

调度类型#

Prefect 支持三种类型的调度:

  • 对于已经熟悉 cron 的用户来说,Cron是最为合适的。

  • Interval最适合那些以某种一致的节奏运行的部署,这种节奏与绝对时间无关。

  • RRule最适合依赖日历逻辑的部署,它适用于简单的循环计划、不规则间隔、排除项或月中某日调整。

调度可处于非激活状态

当您创建或编辑计划时,可以在 Python 中将 active 属性设置为 False(或者在 YAML 文件中设置为 false),以停用该调度。 这一功能有助于保留调度配置,同时临时阻止调度生成新的流程运行。

Cron#

你可以使用cron模式来指定调度。你还可以提供时区,以执行夏令时(DST)的行为。

Prefect 使用 croniter 来指定具有类似 cron 格式的日期时间迭代。

支持的 croniter 功能

虽然Prefect支持大多数 croniter 功能来创建类似 cron 的调度,但它不支持 “R” 随机或 “H” 哈希关键词表达式,或者那些表达式可能实现的时间表抖动。

cron 属性包括:

属性

描述

cron

有效的 cron 字符串。(必需的)

day_or

布尔值,指示 croniter 如何处理 dayday_of_week 条目。默认值为 True

timezone

时区的字符串名称。(查看IANA时区数据库以获取有效时区。)

day_or 属性的工作原理#

day_or 属性默认为 True,与 cron 的行为一致。

在此模式下,如果您指定了一个月中的某一天(day)和一周中的某一天(day_of_week),则计划将在指定的月日和周日均执行一次流程。

day_or 中的 "or" 指的是这两个条目被视为逻辑 “OR” 语句。计划应包括两者,就像 SQL 语句中的那样:

SELECT * FROM employees WHERE first_name = 'Ford' OR last_name = 'Prefect';

例如,当 day_or 设置为 True 时,cron 计划表达式 * * 3 1 2 将在每月的第三天以及每年一月(即一年的第一个月)的星期二(一周中的第二天)每分钟执行一次流程。

day_or 设置为 False 时,“日”(指月份中的日期)和 “星期几” 的条目会通过更为严格的 AND 逻辑操作符连接起来,正如 SQL 语句中所示:

SELECT * from employees WHERE first_name = 'Zaphod' AND last_name = 'Beeblebrox';

例如,当day_or设置为False时,相同的计划表将在1月的第三个星期二每分钟运行一次。 这种行为与fcron相符,而非cron

夏令时考虑事项

如果timezone遵守夏令时,那么计划表会相应地进行调整。

夏令时的cron规则基于计划时间而非间隔。这意味着每小时的cron计划会在每个新的计划小时触发一次,而不是每过一个小时触发一次。 例如,当时钟向后调一小时时,这将导致计划出现两小时的暂停,因为计划将在第一次到达凌晨1点和120分钟后的凌晨2点各触发一次。

更长的计划,例如每天早上9点触发的计划,会自动调整以适应夏令时。

Interval#

Interval 调度器会以秒为单位定期创建新的流程运行。这些间隔是根据可选的 anchor_date 来计算的。

schedule:
  interval: 600
  timezone: America/Chicago

Interval 属性包括:

属性

描述

interval

表示流运行之间时间的 datetime.timedelta。(必填)

anchor_date

表示开始或“锚点”日期以开始计划的 datetime.datetime。如果没有提供 anchor_date,则使用当前的 UTC 时间。

timezone

时区的字符串名称,用于强制执行本地化行为,如夏令时边界。(有关有效时区,请参阅 IANA 时区数据库。)

anchor_date 并不表示计划的“开始时间”,而是用于计算间隔的固定点。 如果锚点日期在未来,则计划日期通过从锚点日期减去 interval 来计算。 在这个示例中,您导入了 Pendulum Python 包,以便于日期时间操作。 Pendulum 不是必需的,但它是一个指定日期的有用工具。

夏令时注意事项

如果计划的 anchor_datetimezone 提供了遵循夏令时的时区,则计划会自行适当调整。 大于 24 小时的间隔将遵循夏令时惯例,而小于 24 小时的间隔将遵循 UTC 间隔。

例如,每小时计划将在每个 UTC 小时触发,即使在夏令时边界也是如此。当时间被拨回时,这会导致两次运行 看起来 被安排在本地时间的 1 点,尽管它们在 UTC 时间上相差一小时。

对于较长的间隔,如每日计划,间隔计划会调整夏令时边界,以便时钟小时保持不变。 这意味着一个总是在上午 9 点触发的每日计划将遵循夏令时,并在本地时区继续在上午 9 点触发。

RRule#

RRule 调度支持 iCal 重复规则(RRules),它提供了方便的语法来创建重复的计划。计划可以按频率从每年到每分钟重复。

RRule 使用 dateutil rrule 模块来指定 iCal 重复规则。

RRules 适用于任何类型的日历日期操作,包括简单的重复、不规则的间隔、排除、工作日或每月的日期调整等。RRules 可以表示复杂的逻辑,例如:

  • 每个月的最后一个工作日

  • 11 月的第四个星期四

  • 每周的每隔一天

RRule 属性包括:

属性

描述

rrule

RRule 计划的字符串表示。有关语法,请参阅 rrulestr 示例

timezone

时区的字符串名称。有关有效时区,请参阅 IANA 时区数据库

您可能会发现使用 RRule 字符串生成器(如 iCalendar.org RRule 工具)来帮助创建有效的 RRules 很有用。

schedule:
  rrule: 'FREQ=WEEKLY;BYDAY=MO,WE,FR;UNTIL=20240730T040000Z'

RRule 限制

rrulestr 支持的最大字符长度为 6,500 个字符

COUNT 不受支持。请使用 UNTIL/deployments/{id}/runs 端点来安排固定数量的流运行。

夏令时注意事项

作为面向日历的标准,RRules 对初始时区很敏感。 一个在夏令时感知开始日期下每天上午 9 点的计划,会在夏令时边界内保持本地时间上午 9 点。一个在 UTC 开始日期下每天上午 9 点的计划,会保持 UTC 时间上午 9 点。

调度的工作原理#

Prefect 的 Scheduler 服务会评估每个部署的计划,并适当地创建新的运行。它在运行 prefect server start 时自动启动,并且是 Prefect Cloud 的内置服务。

Scheduler 会创建满足以下约束的最少运行次数,按顺序:

  • 最多安排 100 次运行。

  • 运行不会安排在超过 100 天后的未来。

  • 至少安排三次运行。

  • 运行将安排到至少一小时后的未来。

这些行为可以通过 prefect config view --show-defaults 命令的相关设置进行调整:

PREFECT_API_SERVICES_SCHEDULER_DEPLOYMENT_BATCH_SIZE='100'
PREFECT_API_SERVICES_SCHEDULER_ENABLED='True'
PREFECT_API_SERVICES_SCHEDULER_INSERT_BATCH_SIZE='500'
PREFECT_API_SERVICES_SCHEDULER_LOOP_SECONDS='60.0'
PREFECT_API_SERVICES_SCHEDULER_MIN_RUNS='3'
PREFECT_API_SERVICES_SCHEDULER_MAX_RUNS='100'
PREFECT_API_SERVICES_SCHEDULER_MIN_SCHEDULED_TIME='1:00:00'
PREFECT_API_SERVICES_SCHEDULER_MAX_SCHEDULED_TIME='100 days, 0:00:00'

请参阅 设置文档 以获取有关更改设置的更多信息。

这些设置意味着,如果部署有一个每小时的计划,默认设置将创建接下来四天(或 100 小时)的运行。如果它有一个每周的计划,默认设置将维持接下来的 14 次运行(最多 100 天后的未来)。

Scheduler 不影响执行

Prefect 的 Scheduler 服务仅创建新的流运行并将它们置于 Scheduled 状态。它不参与流或任务的执行。

如果您更改了计划,之前安排的尚未开始的流运行将被删除,并创建新的安排流运行以反映新的计划。

要删除流部署的所有安排运行,您可以删除该计划。