原文转自微信公众号“ 云计算技术栈“:https://mp.weixin.qq.com/s/scyeGGGHMWZ55A174vAYfQ
airflow 简介
airflow 主要概念
dag 是airflow中组合工作流的方式。是一些操作/步骤的集合。体现了她们之间的执行顺序及依赖关系等。 一般情况下一个dag就对应了一个单独的工作流(workflow)。
airflow 会加载所有它识别到的dag。但是这仅限于python中的global()命名空间中的dag对象,即全局dag。 对于定义在local命名空间如函数中的,可以按考 “subDagOperator“。airflow将不会将其作为独立的dag来处理。BTW,一个dag代表着一个workflow(工作流)。
可以通过在实例化dag的时候传递一个默认参数。这样可以避免 该dag中的每个operator都单独配置相关设置项。
default_args = {
'start_date': datetime(2016, 1, 1),
'owner': 'Airflow'
}
dag = DAG('my_dag', default_args=default_args)
op = DummyOperator(task_id='dummy', dag=dag)
print(op.owner) # Airflow
可以利用python的context manager特性自动将Operator添加到(绑定到)dag上。
# 这里定义的op不需要指定参数dag=dag来绑定到dag
with DAG('my_dag', start_date=datetime(2016, 1, 1)) as dag:
op = DummyOperator('op')
op.dag is dag # True
DAGs定义工作流。Operators来定义具体的工作如何执行。在一个工作流中一个Operator定义一个task。 operator通常是原子的。她们不需要和其他的operator/task交互。dag来定义operator在一个workflow中的执行顺序,一个工作流中的operator甚至可能在不同的机器上执行。需要特别关注这一点,以防止在定义dag的时候想当然的依赖operator的执行环境。
如果两个operator需要共享信息的话,可以通过xComs来实现。
airflow提供了一些常用的Operator:
Operators不是必须要立即绑定到dag上。一旦一个operator绑定到来dag上,它就无法解绑或者转移到别的dag上。
dag = DAG('my_dag', start_date=datetime(2016, 1, 1))
# sets the DAG explicitly
explicit_op = DummyOperator(task_id='op1', dag=dag)
# deferred DAG assignment
deferred_op = DummyOperator(task_id='op2')
deferred_op.dag = dag
# inferred DAG assignment (linked operators must be in the same DAG)
inferred_op = DummyOperator(task_id='op3')
inferred_op.set_upstream(deferred_op)
airflow建议通过 移位操作符来表示 一个dag/workflow中的各operator的依赖关系或执行顺序。它们的效果和 set_upstram()及set_downstram()效果一样。
例如:
# 等价
op1 >> op2
op1.set_downstream(op2)
# 等价
op2 << op1
op2.set_upstream(op1)
# 等价
op1 >> op2 >> op3 << op4
op1.set_downstream(op2)
op2.set_downstream(op3)
op3.set_upstream(op4)
# 等价
dag >> op1 >> op2
op1.dag = dag
op1.set_downstream(op2)
# 等价
op1 >> [op2, op3] >> op4
# 和
op1 >> op2 >> op4
op1 >> op3 >> op4
# 和
op1.set_downstream([op2, op3])
#
with DAG('my_dag', start_date=datetime(2016, 1, 1)) as dag:
(
DummyOperator(task_id='dummy_1')
>> BashOperator(
task_id='bash_1',
bash_command='echo "HELLO!"')
>> PythonOperator(
task_id='python_1',
python_callable=lambda: print("GOODBYE!"))
)
chain 和 cross_downstream 函数在特定情况下给设置operator之间的关系提供了简便方法
# 等价
[op1, op2, op3] >> op4
[op1, op2, op3] >> op5
[op1, op2, op3] >> op6
cross_downstream([op1, op2, op3], [op4, op5, op6])
# 等价
op1 >> op2 >> op3 >> op4 >> op5
chain(op1, op2, op3, op4, op5)
chain([DummyOperator(task_id='op' + i, dag=dag) for i in range(1, 6)])
#等价
chain(op1, [op2, op3], op4)
op1 >> [op2, op3] >> op4
#等价
chain(op1, [op2, op3], [op4, op5], op6)
op1 >> [op2, op3]
op2 >> op4
op3 >> op5
[op4, op5] >> op6
一旦一个operator被实例化,它就被称为一个task。这个class和instances的关系很类似。也就是operator别实例化并称为dag/workfow中的一个节点。
Task Instances 是一次特定的task,由 DAG、task 和 timestemp 来唯一标示。当然它也有自己的状态,如“success”、“failed”、“skipped”等。