目录

  • 导入模块
  • 设置默认参数
  • 实例化一个DAG
  • 任务
  • Templating with Jinja
  • 设置依赖关系
  • 简要重述以上内容
  • 测试

导入模块

# 导入所需的模块
# DAG用来实例化DAG对象,注意仅仅只是定义了一个对象,而不是进行真正的数据处理流程
from airflow import DAG
from airflow.operators.bash_operator import BashOperator
from datetime import datetime, timedelta

设置默认参数

在我们创建任务的时候我们可以使用这些默认参数

default_args = {
    'owner': 'airflow',
    'depends_on_past': False,
    'start_date': datetime(2015, 6, 1),
    'email': ['airflow@example.com'],
    'email_on_failure': False,
    'email_on_retry': False,
    'retries': 1,
    'retry_delay': timedelta(minutes=5),
    # 'queue': 'bash_queue',
    # 'pool': 'backfill',
    # 'priority_weight': 10,
    # 'end_date': datetime(2016, 1, 1),
}

实例化一个DAG

我们需要一个 DAG 对象来嵌入我们的任务,下面的代码中,我们首先定义一个字符串,作为DAG的唯一标识,然后传入默认的参数字典(上面定义的),然后定义调度的间隔为1天

dag = DAG(
    'tutorial', default_args=default_args, schedule_interval=timedelta(days=1))

任务

实例化 operator 时会生成任务。一个从 operator 实例化的对象也称为构造器(constructor),第一个参数 task_id 作为任务的唯一标识

t1 = BashOperator(
    task_id='print_date',
    bash_command='date',
    dag=dag)

t2 = BashOperator(
    task_id='sleep',
    bash_command='sleep 5',
    retries=3,
    dag=dag)

注意我们如何将各个Operator特定的参数(bash_command) 以及继承自BaseOperator的所有Operator的通用参数(retries) 传递给Operator的constructor。这比将每个参数传递给每个constructor要简单。当然我们也注意到,t2继承的通用参数retries被我们重载,赋值成3了。
任务的前提规则如下:

  1. 明确传递参数
  2. 值在default_args字典中存在
  3. operator的默认值(如果存在)
    一个任务必须包含或者继承参数 task_id 与 owner ,否则Airflow 将会抛出异常

Templating with Jinja

Airflow利用Jinja Templating的强大功能,为管道作者提供一组内置参数和宏。Airflow还为管道作者提供了定义自己的参数,宏和模板的钩子(Hooks)。
本教程几乎没有涉及在Airflow中使用模板进行操作,本节的目的是让您了解此功能的存在,让您熟悉双花括号和最常见的模板变量:{{ds}}(今天的“日期戳”)。

templated_command = """
    {% for i in range(5) %}
        echo "{{ ds }}"
        echo "{{ macros.ds_add(ds, 7) }}"
        echo "{{ params.my_param }}"
    {% endfor %}
"""

t3 = BashOperator(
    task_id='templated',
    bash_command=templated_command,
    params={'my_param': 'Parameter I passed in'},
    dag=dag)

请注意,templated_command包含{%%}块中的代码逻辑,引用参数如{{ds}},调用{{macros.ds_add(ds,7)}}中的函数,并在{{params.my_param}}中引用用户定义的参数。

BaseOperator中的params hook允许您将参数和/或对象的字典传递给模板。
请花点时间了解参数my_param如何通过模板。

文件也可以传递给bash_command参数,例如bash_command ='templated_command.sh',其中文件位置相对于包含管道文件的目录(在本例中为tutorial.py)。
这可能有许多种原因,例如分离脚本的逻辑和管道代码,允许在用不同语言编写的文件中执行正确的代码突出显示,以及构造管道的通用性及灵活性。
也可以将template_searchpath定义为指向DAG构造函数调用中的任何文件夹位置。

使用相同的DAG构造函数调用,可以定义user_defined_macros,它允许您指定自己的变量。
例如,将dict(foo ='bar')传递给此参数允许您在模板中使用{{foo}}
此外,指定user_defined_filters允许您注册自己的过滤器。
例如,将dict(hello = lambda name:'Hello%s'%name)传递给此参将允许您在自己的模板中使用{{'world'|{{ 'world' | hello }} 有关自定义过滤器的更多信息,请查看Jinja文档

关于可在模板中引用的变量和宏的更多信息,请务必阅读宏参考

设置依赖关系

我们有互不依赖的三个任务 t1,t2,t3。接下来有一些定义它们之间依赖关系的方法

t1.set_downstream(t2)

# 这个表示t2将依赖于t1
# 等价于
t2.set_upstream(t1)

# 位移运算符也可以完成 t2依赖于t1 的设置
t1 >> t2

# 位移运算符完成 t1依赖于t2 的设置
t2 << t1

# 使用位移运算符更加简洁地设置多个连锁依赖关系
t1 >> t2 >> t3

# 任务列表也可以被设置成依赖,以下几种表达方式是等效的
t1.set_downstream([t2, t3])
t1 >> [t2, t3]
[t2, t3] << t1

请注意,在执行脚本时,Airflow会在DAG中找到循环或多次引用依赖项时引发异常。

简要重述以上内容

我们已经有了十分基础的 DAG 了,你的代码应当看起来和下面给出的差不多

"""
Code that goes along with the Airflow tutorial located at:
https://github.com/apache/airflow/blob/master/airflow/example_dags/tutorial.py
"""
from airflow import DAG
from airflow.operators.bash_operator import BashOperator
from datetime import datetime, timedelta


default_args = {
    'owner': 'airflow',
    'depends_on_past': False,
    'start_date': datetime(2015, 6, 1),
    'email': ['airflow@example.com'],
    'email_on_failure': False,
    'email_on_retry': False,
    'retries': 1,
    'retry_delay': timedelta(minutes=5),
    # 'queue': 'bash_queue',
    # 'pool': 'backfill',
    # 'priority_weight': 10,
    # 'end_date': datetime(2016, 1, 1),
}

dag = DAG(
    'tutorial', default_args=default_args, schedule_interval=timedelta(days=1))

# t1, t2 and t3 are examples of tasks created by instantiating operators
t1 = BashOperator(
    task_id='print_date',
    bash_command='date',
    dag=dag)

t2 = BashOperator(
    task_id='sleep',
    bash_command='sleep 5',
    retries=3,
    dag=dag)

templated_command = """
    {% for i in range(5) %}
        echo "{{ ds }}"
        echo "{{ macros.ds_add(ds, 7)}}"
        echo "{{ params.my_param }}"
    {% endfor %}
"""

t3 = BashOperator(
    task_id='templated',
    bash_command=templated_command,
    params={'my_param': 'Parameter I passed in'},
    dag=dag)

t2.set_upstream(t1)
t3.set_upstream(t1)

测试

运行脚本

是时候进行一些测试了,我们先确保管道解析成功。
首先确认上述的代码已经存入tutorial.py,文件的位置位于你的airflow.cfg指定的 dags 文件夹内,你的DAGs文件夹默认在~/airflow/dags 在命令行执行:

python ~/airflow/dags/tutorial.py

如果这个脚本不抛出异常,则意味着你没有犯任何可怕的错误,而且你的Airflow环境还不错。

命令行元数据验证

让我们运行一些命令来进一步验证上一个脚本

# 打印激活的DAGs 的列表
airflow list_dags

# 打印dag_id 为 "tutorial"  的任务的列表
airflow list_tasks tutorial

#  打印 tutorial DAG中任务的层级关系
airflow list_tasks tutorial --tree

测试

让我们通过在特定日期运行实际任务实例来进行测试。
在此上下文中指定的日期是execution_date,它模拟特定日期+时间调度运行任务或dag:

# command layout: command subcommand dag_id task_id date

# testing print_date
airflow test tutorial print_date 2015-06-01

# testing sleep
airflow test tutorial sleep 2015-06-01

现在还记得我们之前用模板做过的事吗?
通过运行此命令,了解如何呈现和执行此模板:

# testing templated
airflow test tutorial templated 2015-06-01

这应该会显示详细的事件日志并最终运行bash命令并打印结果
请注意,airflow test命令在本地运行任务实例,将其日志输出到stdout(在屏幕上),不依赖于依赖项,并且不向数据库传达状态(运行,成功,失败,...)。
它只允许测试单个任务实例。

backfill

一切看起来都运行良好,让我们运行backfill。
backfill将遵守您的依赖关系,将日志发送到文件并与数据库通信以记录状态。如果您有网络服务器,您还可以跟踪进度。如果您有兴趣在backfill过程中直观地跟踪进度,
airflow webserver将启动Web服务器。
请注意,如果使用depends_on_past = True,则单个任务实例将取决于前面任务实例的成功。但是如果指定了这个任务的start_date,此依赖关系将被忽略。

backfill: 在指定的日期范围内运行DAG的子部分。
如果使用reset_dag_run选项,则backfill将首先提示用户airflow是否应清除backfill日期范围内的所有先前dag_runtask_instances
如果使用rerun_failed_tasks,则backfill将自动重新运行backfill日期范围内的先前失败的任务实例。

``cmd
 airflow backfill [-h] [-t TASK_REGEX] [-s START_DATE] [-e END_DATE] [-m] [-l]
 [-x] [-i] [-I] [-sd SUBDIR] [--pool POOL]
 [--delay_on_limit DELAY_ON_LIMIT] [-dr] [-v] [-c CONF]
 [--reset_dagruns] [--rerun_failed_tasks] [-B]
 dag_id
 ```

此上下文中的日期范围是start_date和可选的end_date,它们用于使用此dag中的任务实例填充运行计划。

# 可选,在后台开启一个web服务器
# airflow webserver --debug &

# 在一个时间范围内开始你的 backfill
airflow backfill tutorial -s 2015-06-01 -e 2015-06-07