原文转自微信公众号“ 云计算技术栈“:https://mp.weixin.qq.com/s/scyeGGGHMWZ55A174vAYfQ
Airflow overview(airflow 初探)
airflow 简介
Airflow 是一个Apache下的顶级开源项目。它基于DAG(Directed Acyclic Graph)有向无环图来组织workflow。提供了可视化的UI可以方便的对系统当前状态,任务执行情况等进行管理。以python代码的形式来实现工作流的定义对程序员非常友好。提供了很多的集成及扩展能力。
airflow 主要概念
airflow 中主要涉及如下核心概念
dag
dag 是airflow中组合工作流的方式。是一些操作/步骤的集合。体现了她们之间的执行顺序及依赖关系等。 一般情况下一个dag就对应了一个单独的工作流(workflow)。
-
Tips:
airflow会自动的扫描 “.py” 结尾的文件来自动发现dag。默认使用的关键字为“DAG”,”airflow“。如果想自定义可以通过设置DAG_DISCOVERY_SAFE_MODE来让airflow自动发现所有文件。
scope
airflow 会加载所有它识别到的dag。但是这仅限于python中的global()命名空间中的dag对象,即全局dag。 对于定义在local命名空间如函数中的,可以按考 “subDagOperator“。airflow将不会将其作为独立的dag来处理。BTW,一个dag代表着一个workflow(工作流)。
default arguments
可以通过在实例化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
context manager
可以利用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
Operators
DAGs定义工作流。Operators来定义具体的工作如何执行。在一个工作流中一个Operator定义一个task。 operator通常是原子的。她们不需要和其他的operator/task交互。dag来定义operator在一个workflow中的执行顺序,一个工作流中的operator甚至可能在不同的机器上执行。需要特别关注这一点,以防止在定义dag的时候想当然的依赖operator的执行环境。
如果两个operator需要共享信息的话,可以通过xComs来实现。
airflow提供了一些常用的Operator:
- BashOperator - 执行bash命令
- PythonOperator - 可以通过python代码来定义task内容。
- EmailOperator - 发送Email通知(需要在airflow.conf中配置相关信息)
- SimpleHttpOperator - 发送http请求
- MySqlOperator, SqletOperator, MsSqlOperator, OracleOperator, JdbcOperator - 执行sql操作。
- Sensor - 等待一定的时间,file/database,row, s3等(TODO:zzh:没有太理解)
只有当Operator绑定到dag上时,airflow才会加载它。
DAG Assignment
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)
Bitshift Composition
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!"))
)
Relationship Helper
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
Task
一旦一个operator被实例化,它就被称为一个task。这个class和instances的关系很类似。也就是operator别实例化并称为dag/workfow中的一个节点。
Task Instances
Task Instances 是一次特定的task,由 DAG、task 和 timestemp 来唯一标示。当然它也有自己的状态,如“success”、“failed”、“skipped”等。