Apache Airflow 1.10+;调度器支持在特定时间在不同的DST感知时区运行2个DAG吗?
Apache引入了对DST感知的本机支持 这使我想到(可能是错误的)应该可以在同一个气流调度器上创建2个DAG,如下所示:Apache Airflow 1.10+;调度器支持在特定时间在不同的DST感知时区运行2个DAG吗?,airflow,airflow-scheduler,Airflow,Airflow Scheduler,Apache引入了对DST感知的本机支持 这使我想到(可能是错误的)应该可以在同一个气流调度器上创建2个DAG,如下所示: 每天06:00太平洋/奥克兰时间开始 每天从美国/纽约时间21:00开始 无需引入“睡眠”到所需开始时间的任务。该文档明确排除了用于DST感知调度的cron调度器,但仅解释了如何将DAG设置为每天在该时区(默认为午夜)运行 以前关于此主题的问题只考虑了使用or,其基础是没有引入对DST感知时区的本机支持 在“airflow.cfg”中,我将默认时区更新为系统时区。然后我
- 每天06:00太平洋/奥克兰时间开始
- 每天从美国/纽约时间21:00开始
DAG('NZ_SOD',
description='New Zealand Start of Day',
start_date=datetime(2018, 12, 11, 06, 00, tzinfo=pendulum.timezone('Pacific/Auckland')),
catchup=False)
以及:
但是,似乎在Apache中没有明确考虑传递给start\u date
的datetime对象的“时间”部分,并创建了意外的行为
气流是否有任何内置选项来产生所需的行为,或者我是否试图使用错误的工具进行作业?首先是一些细节:
- 不要使用前导0(如06 am)指定日期时间,因为如果匆忙将其编辑到上午9点,您将发现这不是有效的八进制数,整个DAG文件将停止解析
- 您也可以使用钟摆符号:
start\u date=be摆.datetime(2018,12,11,6,0,tz='Pacific/Auckland')
[core]
default_timezone = America/New_York
带有开始日期
如:
start_date = datetime(2018, 12, 11, 6, 0),
UTC为-18000
或-5h时,您将获得偏移量
start_date = datetime(2018, 4, 11, 6, 0),
UTC为-14400
或-4h时,您将获得偏移量
其中,第二个项目符号中的偏移量为46800
或13h,而4月份奥克兰的偏移量为43200
或12h。如果我回忆正确,这些将应用于DAG的计划间隔
文档似乎在说,您的schedule\u interval
crontab字符串将永远在同一偏移量中解释。因此,05***
如果你在12月份在纽约开始,那么它将在早上5点或6点运行;如果你在4月份在纽约开始,那么它将在早上5点或4点运行。UH我想那是对的。我对此也感到困惑
将默认值保留为utc并不能避免这种情况。不,如果您使用所示的开始日期
并选择了与utc的偏移量不同的区域,则不会
现在…第二个问题,每天的时间。开始日期是有效的最早开始时间间隔。一天中的某个时间很好,但日程安排默认为timedelta(days=1)
。我以为它是@daily
,也就是0***
,给你带来了有趣的结果,比如从12月11日上午6点开始,你的第一个完整的午夜到午夜间隔将在12月13日午夜结束,因此,第一次运行在12月12日午夜被传递为执行日期。但我预计,如果将timedelta
应用于开始日期
,它将在12月12日早上6点开始,昨天的时间与执行日期
相同。然而,我没有看到它是这样工作的,这确实让我认为它可能只使用了datetime
中的datetime
部分作为start\u date
的某个地方
如文件所述,传入的执行日期
(以及所有宏日期)将以UTC为单位(因此,您的开始日期
时区偏移中的午夜或早上6点转换为UTC)。至少它们附带了tz,因此如果必须,您可以在它们上使用convert
。答案是肯定的,cron时间表支持在支持DST的时区中运行DAG
但是有很多警告,所以我不得不假设气流的维护者没有将其作为一个受支持的用例。首先,截至撰写本报告时,当声明:
Cron调度
在设置cron计划的情况下,气流假设您始终希望在完全相同的时间运行。然后,它将忽略日光节约时间。因此,如果您有一个时间表,上面写着在每天08:00 GMT+1的时间间隔结束时运行,它将始终在08:00 GMT+1的时间间隔结束时运行,无论是否有日光节约时间
我编写了这段有点粗糙的代码,让您了解在不需要运行Airflow实例的情况下时间表是如何工作的(请注意,您安装了Penulum 1.x,如果您运行或编辑此代码,请使用正确的:
正如我们可以看到的,DST是使用cron计划观察到的,进一步说,如果您编辑我的代码以删除cron计划,您可以看到DST是未观察到的
但请注意,即使cron计划遵守DST,您可能仍然会在DST更改当天出现“按1天计算”错误,因为Airflow提供的是以前的日期,而不是当前日期(例如日历上的星期日,但在Airflow中,执行日期是星期六)。在我看来,这并不是在follow\u计划中考虑的
最后,@dlamblin指出,如果DAG的本地执行日期与UTC执行日期不相同,则Airflow通过模板字符串或provide_context=True
为Python可调用项提供的变量将是错误的。这可以通过使用self来观察
start_date = datetime(2018, 4, 11, 6, 0),
import pendulum
from airflow import DAG
from datetime import timedelta
# Set-up DAG
test_dag = DAG(
dag_id='foo',
start_date=pendulum.datetime(year=2019, month=4, day=4, tz='Pacific/Auckland'),
schedule_interval='00 03 * * *',
catchup=False
)
# Check initial schedule
execution_date = test_dag.start_date
for _ in range(7):
next_execution_date = test_dag.following_schedule(execution_date)
if next_execution_date <= execution_date:
execution_date = test_dag.following_schedule(execution_date + timedelta(hours=2))
else:
execution_date = next_execution_date
print('Execution Date:', execution_date)
Execution Date: 2019-04-03 14:00:00+00:00
Execution Date: 2019-04-04 14:00:00+00:00
Execution Date: 2019-04-05 14:00:00+00:00
Execution Date: 2019-04-06 14:00:00+00:00
Execution Date: 2019-04-07 15:00:00+00:00
Execution Date: 2019-04-08 15:00:00+00:00
Execution Date: 2019-04-09 15:00:00+00:00
import datetime
def foo(*args, dag, execution_date, **kwargs):
# Derive local execution datetime from dag and execution_date that
# airflow passes to python callables where provide_context is set to True
airflow_timezone = dag.timezone
local_execution_datetime = airflow_timezone.convert(execution_date)
# I then add 1 day to make it the calendar day
# and not the execution date which Airflow provides
local_cal_datetime = local_execution_datetime + datetime.timedelta(days=1)
# Standard Library
import datetime
# Third Party Libraries
import airflow.operators.email_operator
import airflow.operators.python_operator
import airflow.operators.bash_operator
class CustomTemplateVarsMixin:
def render_template(self, attr, content, context):
# Do Calculations
airflow_execution_datetime = context['execution_date']
airflow_timezone = context['dag'].timezone
local_execution_datetime = airflow_timezone.convert(airflow_execution_datetime)
local_cal_datetime = local_execution_datetime + datetime.timedelta(days=1)
# Add to contexts
context['local_cal_datetime'] = local_cal_datetime
# Run normal Method
return super().render_template(self, attr, content, context)
class BashOperator(CustomTemplateVarsMixin, airflow.operators.bash_operator.BashOperator):
pass
class EmailOperator(CustomTemplateVarsMixin, airflow.operators.email_operator.EmailOperator):
pass
class PythonOperator(CustomTemplateVarsMixin, airflow.operators.python_operator.PythonOperator):
pass
class BranchPythonOperator(CustomTemplateVarsMixin, airflow.operators.python_operator.BranchPythonOperator):
pass