什么是Airflow?
Airflow 是一個(gè)使用 python 語言編寫的 data pipeline 調(diào)度和監(jiān)控工作流的平臺(tái)。Airflow 被 Airbnb 內(nèi)部用來創(chuàng)建、監(jiān)控和調(diào)整數(shù)據(jù)管道。任何工作流都可以在這個(gè)使用 Python 來編寫的平臺(tái)上運(yùn)行。Airflow是通過DAG(Directed acyclic graph)來管理任務(wù)流程的任務(wù)調(diào)度工具,她不需要知道業(yè)務(wù)數(shù)據(jù)的具體內(nèi)容,設(shè)置任務(wù)的依賴關(guān)系實(shí)現(xiàn)任務(wù)調(diào)度。
這個(gè)平臺(tái)擁有和 Hive、Presto、MySQL、HDFS、Postgres 和 S3 交互的能力,并且提供了鉤子(hook)使得系統(tǒng)擁有很好地?cái)U(kuò)展性。除了一個(gè)命令行界面,該工具還提供了一個(gè)基于 Web 的用戶界面讓您可以可視化管道的依賴關(guān)系、監(jiān)控進(jìn)度、觸發(fā)任務(wù)等。
Airflow 的架構(gòu)
在一個(gè)可擴(kuò)展的生產(chǎn)環(huán)境中,Airflow 含有以下組件:
- 一個(gè)元數(shù)據(jù)庫(kù)(MySQL 或 Postgres)
- 一組 Airflow 工作節(jié)點(diǎn)
- 一個(gè)調(diào)節(jié)器(Redis 或 RabbitMQ)
-
一個(gè) Airflow Web 服務(wù)器
Airflow Scheduler
功能簡(jiǎn)介
任務(wù)依賴
通常,在一個(gè)運(yùn)維系統(tǒng),數(shù)據(jù)分析系統(tǒng),或測(cè)試系統(tǒng)等大型系統(tǒng)中,我們會(huì)有各種各樣的依賴需求。比如:
- 時(shí)間依賴:任務(wù)需要等待某一個(gè)時(shí)間點(diǎn)觸發(fā)。
- 外部系統(tǒng)依賴:任務(wù)依賴 Mysql 中的數(shù)據(jù),HDFS 中的數(shù)據(jù)等等,這些不同的外部系統(tǒng)需要調(diào)用接口去訪問。
- 機(jī)器依賴:任務(wù)的執(zhí)行只能在特定的某一臺(tái)機(jī)器的環(huán)境中,可能這臺(tái)機(jī)器內(nèi)存比較大,也可能只有那臺(tái)機(jī)器上有特殊的庫(kù)文件。
- 任務(wù)間依賴:任務(wù) A 需要在任務(wù) B 完成后啟動(dòng),兩個(gè)任務(wù)互相間會(huì)產(chǎn)生影響。
- 資源依賴:任務(wù)消耗資源非常多,使用同一個(gè)資源的任務(wù)需要被限制,比如跑個(gè)數(shù)據(jù)轉(zhuǎn)換任務(wù)要10個(gè) G,機(jī)器一共就30個(gè) G,最多只能跑兩個(gè),我希望類似的任務(wù)排個(gè)隊(duì)。
- 權(quán)限依賴:某種任務(wù)只能由某個(gè)權(quán)限的用戶啟動(dòng)。
也許大家會(huì)覺得這些是在任務(wù)程序中的邏輯需要處理的部分,但是我認(rèn)為,這些邏輯可以抽象為任務(wù)控制邏輯的部分,和實(shí)際任務(wù)執(zhí)行邏輯解耦合。
Airflow的處理依賴的方式
Airflow 和crontab不同。crontab 可以很好地處理定時(shí)執(zhí)行任務(wù)的需求,它是一種依賴管理系統(tǒng),而且只管理時(shí)間上的依賴。Airflow 的核心概念,是 DAG (有向無環(huán)圖),DAG 由一個(gè)或多個(gè) TASK 組成,而這個(gè) DAG 正是解決了上文所說的任務(wù)間依賴。Task A 執(zhí)行完成后才能執(zhí)行 Task B,多個(gè)Task之間的依賴關(guān)系可以很好的用DAG表示完善。
Airflow 完整的支持 crontab 表達(dá)式,也支持直接使用 python 的 datatime 表述時(shí)間,還可以用 datatime 的 delta 表述時(shí)間差。這樣可以解決任務(wù)的時(shí)間依賴問題。
Airflow 在 CeleryExecuter 下可以使用不同的用戶啟動(dòng) Worke r,不同的 Worker 監(jiān)聽不同的 Queue ,這樣可以解決用戶權(quán)限依賴問題。Worker 也可以啟動(dòng)在多個(gè)不同的機(jī)器上,解決機(jī)器依賴的問題。
Airflow 可以為任意一個(gè) Task 指定一個(gè)抽象的 Pool,每個(gè) Pool 可以指定一個(gè) Slot 數(shù)。每當(dāng)一個(gè) Task 啟動(dòng)時(shí),就占用一個(gè) Slot ,當(dāng) Slot 數(shù)占滿時(shí),其余的任務(wù)就處于等待狀態(tài)。這樣就解決了資源依賴問題。
Airflow 中有 Hook 機(jī)制(其實(shí)我覺得不應(yīng)該叫 Hook ),作用時(shí)建立一個(gè)與外部數(shù)據(jù)系統(tǒng)之間的連接,比如 Mysql,HDFS,本地文件系統(tǒng)(文件系統(tǒng)也被認(rèn)為是外部系統(tǒng))等,通過拓展 Hook 能夠接入任意的外部系統(tǒng)的接口進(jìn)行連接,這樣就解決的外部系統(tǒng)依賴問題。
Airflow的命令
- airflow webserver -p 8080 打開webserver
- airflow scheduler 調(diào)度器,必須啟動(dòng),不然dag沒法run起來(使用CeleryExecutor、LocalExecutor時(shí))
- airflow run dagid [time] run task instance
- airflow backfill [dagid] -s[startTime] -e [endTime] run a backfill over 2 days
run的demo
# run your first task instance
airflow run example_bash_operator runme_0 2018-01-11
# run a backfill over 2 days
airflow backfill example_bash_operator -s 2018-01-10 -e 2018-01-11
基于CeleryExecutor方式的系統(tǒng)架構(gòu)
基于CeleryExecutor方式的系統(tǒng)架構(gòu)
使用celery方式的系統(tǒng)架構(gòu)圖(官方推薦使用這種方式,同時(shí)支持mesos方式部署)。turing為外部系統(tǒng),GDags服務(wù)幫助拼接成dag,可以忽略。
1.master節(jié)點(diǎn)webui管理dags、日志等信息。scheduler負(fù)責(zé)調(diào)度,只支持單節(jié)點(diǎn),多節(jié)點(diǎn)啟動(dòng)scheduler可能會(huì)掛掉
2.worker負(fù)責(zé)執(zhí)行具體dag中的task。這樣不同的task可以在不同的環(huán)境中執(zhí)行。
基于LocalExecutor方式的系統(tǒng)架構(gòu)圖
另一種啟動(dòng)方式的思考,一個(gè)dag分配到1臺(tái)機(jī)器上執(zhí)行。如果task不復(fù)雜同時(shí)task環(huán)境相同,可以采用這種方式,方便擴(kuò)容、管理,同時(shí)沒有master單點(diǎn)問題。
從安裝airflow到成功運(yùn)行,踩了很多坑,憑借著回憶簡(jiǎn)單記錄一下。
運(yùn)行常用命令
- Initialize the db 第一次安裝完初始化airflow
airflow initdb
- 開啟webserver,登陸網(wǎng)頁(yè)http://localhost:8080可以看到dag運(yùn)行狀況
airflow webserver --port 8080
- test the 單個(gè)DAG
$ python airflow_dag.py #先編譯python
編譯成功之后test:
#格式:airflow test dag_id task_id execution_time
$ airflow test airflow_tutorial print_world 2017-07-01
- 測(cè)試成功之后運(yùn)行
#開啟調(diào)度任務(wù)器
$ airflow scheduler
# 開始運(yùn)行任務(wù)
$ airflow trigger {$dag}.py
這一步也可以在web界面點(diǎn)trigger按鈕
一點(diǎn)總結(jié)
我用airflow執(zhí)行的任務(wù)是從一個(gè)數(shù)據(jù)庫(kù)中同步數(shù)據(jù)到另一個(gè)數(shù)據(jù)庫(kù)。本來想用airflow里的hook連數(shù)據(jù)庫(kù),進(jìn)行同步,但是程序死卡在running死活不運(yùn)行。這樣研究了好久也沒研究出來原因。網(wǎng)上關(guān)于airflow的文檔都停留在介紹和入門,很少有實(shí)際運(yùn)行的例子。
后來才發(fā)現(xiàn),其實(shí)沒必要非去使用airflow連數(shù)據(jù)庫(kù)的方法。airflow相當(dāng)于一個(gè)工具,一個(gè)嵌入在python文件中的工具。所以在寫airflow時(shí),其他部分功能定義正常寫,連數(shù)據(jù)庫(kù)啊,分割字符串啊,這些都按照python里的方法來寫就可以了,最后再用airflow定義task前后依賴關(guān)系。
搞清楚這點(diǎn),就會(huì)發(fā)現(xiàn)其實(shí)airflow非常好用。