1. DAG
在Airflow中,DAG或有向無環圖是你運行所有任務的集合,以某種組織方式來反映所有任務之間的關係和依賴。
例如,一個簡單的DAG可以包括三個任務:A,B和C.可以說A必須在B運行之前成功運行,但C可以隨時運行。 可以說任務A在5分鐘後超時,爲防止失敗,B可以最多重啓5次。也可以說工作流從某個特定日期開始每晚10點運行。
以這種方式,DAG描述了你如何執行工作流程; 但是請注意,我們還沒有說出我們實際想要做的事情! A,B和C可以是任何東西。也許在C發送電子郵件時,A爲B準備數據以進行分析。或者A監視你的位置,以便B可以打開你的車庫門,而C打開房子的燈。重要的是,DAG不關心其內部任務幹了什麼;它的目的是確保在正確的時間或以正確的順序幹任何事情,或可以正確處理任何意想不到的問題。
DAG在標準的Python文件中定義,放置在Airflow的DAG_FOLDER
中。Airflow將執行每個文件中的代碼來動態構建DAG對象。你可以擁有任意數量的DAG,每個可以擁有任意數量的任務。通常,每一個應該對應於一個邏輯工作流。
1.1 作用域(scope)
Airflow將加載從DAG文件導入的任何DAG對象。最重要的是,這意味着DAG必須出現在globals()
中。考慮以下兩個DAG。只有dag_1
將被加載;另一個只出現在局部作用域內。
dag_1 = DAG('this_dag_will_be_discovered')
def my_function()
dag_2 = DAG('but_this_dag_will_not')
my_function()
有時這有很好的用處。例如,SubDagOperator
的通用模式是在函數內定義子dag,以便Airflow不會將其作爲獨立DAG進行加載。
1.2 默認參數
如果將default_args
字典傳遞給DAG,DAG將會將字典應用於其內部的任何Operator上。這很容易的將常用參數應用於多個Operator,而無需多次鍵入。
default_args=dict(
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
1.3 上下文管理器(Context Manager)
備註
Airflow 1.8引入
DAG可用作上下文管理器,以自動爲DAG分配新的Operator。
with DAG('my_dag', start_date=datetime(2016, 1, 1)) as dag:
op = DummyOperator('op')
op.dag is dag # True
2. Operators
DAG描述瞭如何運行工作流,Operators
決定了實際如何完成。
Operator描述了工作流中的單個任務。Operator通常(但不總是)原子性的,這意味着它們可以獨立存在,不需要與其他Operator共享資源。DAG將確保Operator按正確的順序運行; 除了這些依賴之外,Operator通常獨立運行。實際上,他們可能會運行在兩臺完全不同的機器上。
這是一個微小但非常重要的一點:一般來說,如果兩個Operator需要共享信息,如文件名或少量數據,則應考慮將它們組合成一個Operator。如果絕對不可避免,Airflow確實有一個名爲XCom
的Operator可以交叉通信。
Airflow爲Operator提供許多常見任務,包括:
BashOperator
- 執行bash命令PythonOperator
- 調用任意的Python函數EmailOperator
- 發送郵件HTTPOperator
- 發送 HTTP 請求SqlOperator
- 執行 SQL 命令Sensor
- 等待一定時間,文件,數據庫行,S3鍵等...
除了這些基本的構建塊之外,還有更多的特定Operator:DockerOperator
,HiveOperator
,S3FileTransferOperator
,PrestoToMysqlOperator
,SlackOperator
...總之你能想到的!
airflow/contrib/
目錄包含更多由社區建立的Operator。這些Operator並不總是與主包(in the main distribution)中的Operator一樣完整或經過很好的測試,但允許用戶更輕鬆地向平臺添加新功能。
Operators只有在分配給DAG時,纔會被Airflow加載。
2.1 DAG分配
備註
在Airflow 1.8版本中引入
Operator不需要立即分配給DAG(以前dag是必需的參數)。但是一旦operator分配給DAG, 它就不能transferred或者unassigned. 當一個Operator創建時,通過延遲分配或甚至從其他Operator推斷,可以讓DAG得到明確的分配(DAG assignment can be done explicitly when the operator is created, through deferred assignment, or even inferred from other operators.).
dag = DAG('my_dag', start_date=datetime(2016, 1, 1))
# 明確指定DAG
explicit_op = DummyOperator(task_id='op1', dag=dag)
# 延遲分配
deferred_op = DummyOperator(task_id='op2')
deferred_op.dag = dag
# 從其他Operator推斷 (linked operators must be in the same DAG)
inferred_op = DummyOperator(task_id='op3')
inferred_op.set_upstream(deferred_op)
2.2 位移組合
備註
在Airflow 1.8版本中引入
傳統上,使用set_upstream()
和set_downstream()
方法來設置Operator之間的依賴關係。在Airflow 1.8中,可以使用Python位移操作符>>
和<<
。 以下四個語句在功能上相當:
op1 >> op2
op1.set_downstream(op2)
op2 << op1
op2.set_upstream(op1)
當使用位移操作符去設置Operator依賴關係時,根據位移操作符指向的方向來判斷Operator之間的依賴關係。例如,op1 >> op2
表示op1先運行,op2然後運行。可以組合多個Operator - 記住從左到右執行的鏈,總是返回最右邊的對象。 例如:
op1 >> op2 >> op3 << op4
等價於:
op1.set_downstream(op2)
op2.set_downstream(op3)
op3.set_upstream(op4)
爲方便起見,位移操作符也可以與DAG一起使用。 例如:
dag >> op1 >> op2
等價於:
op1.dag = dag
op1.set_downstream(op2)
我們可以把這一切整合在一起,建立一個簡單的管道:
with DAG('my_dag', start_date=datetime(2016, 1, 1)) as dag:
(
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!"))
)
3. Task
一旦Operator被實例化,它被稱爲"任務"。實例化爲在調用抽象Operator時定義一些特定值,參數化任務使之成爲DAG中的一個節點。
4. 任務實例化
一個任務實例表示任務的一次特定運行,並且被表徵爲dag,任務和時間點的組合。任務實例也有指示性狀態,可能是“運行”,“成功”,“失敗”,“跳過”,“重試”等。
5. 工作流
現在你已經熟悉了Airflow的核心構建塊。一些概念可能聽起來似曾相似,但詞彙可以這樣概念化:
- DAG:描述工作發生的順序
- Operator:執行某些工作的模板類
- Task:Operator的參數化實例
- TaskInstances(任務實例):1)已分配給DAG的任務,2)具有DAG特定運行相關的狀態
通過組合DAG
和Operators
來創建TaskInstances
,可以構建複雜的工作流。