Airflow 是什麼
Airflow 是 Airbnb 開發的用於工作流管理的開源專案,自帶 web UI 和排程。現在 Apache 下做孵化,地址是 github.com/apache/incu…
Airflow 解決什麼問題
Airflow 主要解決的問題可以參考 Airbnb 官方的部落格: airflow-a-workflow-management-platform,簡單來說就是管理和排程各種離線定時 Job ,可以替代 crontab。
當 cron job 規模達到數百上千時,其對人的要求將會非常高的,如果你的團隊經歷過這樣的事情,應該能體會其中痛苦,所以使用類似 airflow 這樣的工具代替 cron 來做定時任務將會極大提高工作效率。
開始使用 airflow 之前需要知道和準備的
Airflow 在 pip 上已經更名為 apache-airflow
,下載最新版請使用後者 pip install apache-airflow
。
Airflow 1.8 版本依賴的是 MySQL 5.6 以上,5.7 以下報 1071, u'Specified key was too long; max key length is 767 bytes
,如果你使用 MySQL 作為你的 airflow backend 請升級你的 MySQL 到最新版。
MySQL 5.6 升級到 5.7 在使用 airflow 時會報 1146, u"Table 'performance_schema.session_variables' doesn't exist"
,執行 mysql_upgrade -u root -p --force
解決。
Airflow 的 mysql driver 使用的是 mysqlclient mysql://root:@127.0.0.1/sqlalchemy_lab?charset=utf8
,如果使用其他 driver 將報 syntax error。
基礎概念
Airflow 中最基本的兩個概念是:DAG 和 task。DAG 的全稱是 Directed Acyclic Graph 是所有你想執行的任務的集合,在這個集合中你定義了他們的依賴關係,一個 DAG 是指一個 DAG object,一個 DAG object 可以在 Python 指令碼中配置完成。
比如一個簡單的的 DAG 包含三個 task:A、B、C,A 執行成功之後 B 才能執行,C 不依賴 A 和 B 即可執行。在這個簡單的 DAG 中 A B C 可以是任何你想要執行的任務。
DAG 的定義使用 Python 完成的,其實就是一個 Python 檔案,存放在 DAG 目錄,Airflow 會動態的從這個目錄構建 DAG object,每個 DAG object 代表了一個 workflow,每個 workflow 都可以包含任意個 task。
安裝和使用
Airflow 是基於 Python 構建的,可以很容易用 pip 安裝使用,pip install apache-airflow
,預設情況下 airflow 會在 ~/airflow
目錄存放相關配置。
Airflow 提供了一些列命令來完成 airflow 的初始化工作來和它的正確使用。
# 在 airflow 目錄初始化資料庫和 airflow 配置
airflow initdb
# 啟動 airflow web
airflow webserver
# 開始排程
airflow scheduler複製程式碼
更詳細的資訊請參考文件 airflow.incubator.apache.org/
第一個 DAG
DAG 的配置用 Python 完成像這樣:
"""
Code that goes along with the Airflow tutorial located at:
https://github.com/airbnb/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@airflow.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(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) # t2 依賴 t1
t3.set_upstream(t1)複製程式碼
DAG 指令碼的目的只是定義 DAG 的配置,並不包含任何的資料處理,在這裡 operator 就是 task。
DAG 的例項化
一個 DAG 指令碼是由 DAG object 的例項化和對應的 operator 組成的,除此之外我們還可以定義預設的引數提供給每個任務。
DAG 物件例項化可以根據我們的需要提供對應的初始化引數,例項化 DAG 物件需要提供唯一的 dag_id:
dag = DAG(
'tutorial', default_args=default_args, schedule_interval=timedelta(1))複製程式碼
Task 的例項化
t1 = BashOperator(
task_id='print_date',
bash_command='date',
dag=dag)
t2 = BashOperator(
task_id='sleep',
bash_command='sleep 5',
retries=3,
dag=dag)複製程式碼
task 物件的定義的就是 operator 的例項化,operator 有 task_id,用來區分任務,可以按照需要定製 bash_command,也可以傳遞引數等。
Task 的依賴
Task 之間是能相互建立依賴的,形如:
t2.set_upstream(t1)
# This means that t2 will depend on t1
# running successfully to run
# It is equivalent to
# t1.set_downstream(t2)
t3.set_upstream(t1)
# all of this is equivalent to
# dag.set_dependency('print_date', 'sleep')
# dag.set_dependency('print_date', 'templated')複製程式碼
Airflow 會自動檢測環形依賴以防止 task 無法工作的情況出現,更復雜的情況請參考文件。
執行和測試
和 airflow.cfg 同級目錄下建立 dag 目錄,用來存放第一個 DAG 指令碼,然後執行 python tutorial.py
,如果沒有報錯說明 tutorial 建立成功了。
Airflow 的命令列
Airflow 提供了一些列的命令列用來檢視 DAG 和 task
# print the list of active DAGs
airflow list_dags
# prints the list of tasks the "tutorial" dag_id
airflow list_tasks tutorial
# prints the hierarchy of tasks in the tutorial DAG
airflow list_tasks tutorial --tree複製程式碼
測試任務的執行
執行任務很簡單,指定 DAG 並去指定 task 和執行的日期
# 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複製程式碼
test 命令會執行任務並且輸出到控制檯,不會把任務的執行狀態進行持久化
執行任務和並記錄狀態
執行任務在 Airflow 中稱之為 backfill,以 backfill 執行會真正開始追蹤任務的執行狀態和依賴,並且會記錄日誌
# optional, start a web server in debug mode in the background
# airflow webserver --debug &
# start your backfill on a date range
airflow backfill tutorial -s 2015-06-01 -e 2015-06-07複製程式碼
更多關於 DAG 和 operator
DAG 的 scope
Airflow 會預設載入任意它能匯入到餓 DAG object,這就意味著只要是全域性的 DAG object 都可以被匯入,但是有時候為了讓 DAG 不被匯入,比如 SubDagOperator 就可以使用 local 的作用域。
dag_1 = DAG('this_dag_will_be_discovered')
def my_function()
dag_2 = DAG('but_this_dag_will_not')
my_function()複製程式碼
DAG 可以指定預設的引數
DAG 的預設引數會應用到所有的 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複製程式碼
擴充套件性極強的 operator
Airflow operator 很容易擴充套件,這也是 airflow 幾乎支援任何形式 task 重要原因。雖然 Airflow 支援不同的 task 可以傳輸資料,但是如果你的兩個 task 之間確實需要共享資料,最好的辦法是把他們寫在一起。
參考資料
- airflow.incubator.apache.org/
- github.com/apache/incu…
- medium.com/airbnb-engi…
- Airflow 測試 demo github.com/zhyq0826/ai…
更多原創文章,關注 wecatch 公眾號