【问题标题】:How to consider daylight savings time when using cron schedule in Airflow在 Airflow 中使用 cron 计划时如何考虑夏令时
【发布时间】:2019-11-30 20:41:16
【问题描述】:

在 Airflow 中,我希望在非 UTC 时区每天的特定时间运行作业。我该如何安排这个?

问题是,一旦触发夏令时,我的工作要么运行得太快一个小时,要么太迟一个小时。 In the Airflow docs,看来这是一个已知问题:

如果你设置了一个 cron 计划,Airflow 会假设你总是想要 在完全相同的时间运行。然后它将忽略日光节约 时间。因此,如果您有一个计划在间隔结束时运行 每天 08:00 GMT+1 它总是会在 08:00 间隔结束时运行 GMT+1,无论是否有夏令时。

还有其他人遇到过这个问题吗?有解决办法吗?当然,最好的做法不能是在夏令时发生后更改所有预定时间吗?

谢谢。

【问题讨论】:

    标签: airflow


    【解决方案1】:

    从 Airflow 1.10 开始,时区感知 DAG 可以使用时区感知 datetime 对象来指定 start_date 来定义。要让 Airflow 始终在同一时间安排 DAG 运行(不管可能的夏令时切换),请使用 cron 表达式指定 schedule_interval。要使 Airflow schedule DAG 以固定的时间间隔运行(不管可能的夏令时切换),请使用 datetime.timedelta() 指定 schedule_interval

    例如,考虑以下代码,首先使用一个 cron 表达式来安排两个连续的 DAG 运行,然后使用一个固定的时间间隔来做同样的事情。

    import pendulum
    from airflow import DAG
    from datetime import datetime, timedelta
    
    START_DATE = datetime(
        year=2019,
        month=10,
        day=25,
        hour=8,
        minute=0,
        tzinfo=pendulum.timezone('Europe/Kiev'),
    )
    
    
    def gen_execution_dates(start_date, schedule_interval):
        dag = DAG(
            dag_id='id', start_date=start_date, schedule_interval=schedule_interval
        )
        execution_date = dag.start_date
        for i in range(1, 3):
            execution_date = dag.following_schedule(execution_date)
            print(
                f'[Run {i}: Execution Date for "{schedule_interval}"]:',
                dag.timezone.convert(execution_date),
            )
    
    
    gen_execution_dates(START_DATE, '0 8 * * *')
    gen_execution_dates(START_DATE, timedelta(days=1))
    

    运行代码会产生以下输出:

    [Run 1: Execution Date for "0 8 * * *"]: 2019-10-26 08:00:00+03:00
    [Run 2: Execution Date for "0 8 * * *"]: 2019-10-27 08:00:00+02:00
    [Run 1: Execution Date for "1 day, 0:00:00"]: 2019-10-26 08:00:00+03:00
    [Run 2: Execution Date for "1 day, 0:00:00"]: 2019-10-27 07:00:00+02:00
    

    对于 [欧洲/基辅] 区域,2019 年的夏令时于 2019 年 10 月 27 日 03:00:00+03:00 结束。也就是说,在我们的示例中,在 Run 1 和 Run 2 之间。

    前两个输出行显示,对于使用 cron 表达式安排的 DAG 运行,第一次运行和第二次运行都安排在 08:00(尽管在不同的时区:东欧夏令时间 (EEST) 和东欧时间(EET))。

    最后两行输出显示,对于以固定间隔安排的 DAG 运行,第一次运行安排在 08:00 (EEST),第二次运行安排在 1 天(24 小时)之后,即由于夏令时切换,07:00 (EET)。

    下图举例说明:

    【讨论】:

    • 太棒了。谢谢。是否可以持续使用这个时区/开始日期?例如,让工作连续运行,而不是一次性运行?
    • @ScottSkiles 默认计划是schedule_interval=datetime.timedelta(1)(每天)。您可以根据需要在default_args 中重新定义它。例如:schedule_interval=datetime.timedelta(hours=1)(每小时)。
    • 这会正确地将 start_date 设置为正确的时区,但间隔不是时区感知的。即使正确的增量是 23 小时或 25 小时,它也会增加 24 小时。
    • @emote_control 我已经扩展了答案以解释 cron 和 timedelta 计划之间的区别。
    猜你喜欢
    • 1970-01-01
    • 2011-08-14
    • 2021-11-07
    • 2013-09-22
    • 1970-01-01
    • 1970-01-01
    • 2018-01-01
    • 2012-07-03
    • 2021-06-10
    相关资源
    最近更新 更多