Azkaban調研

Azkaban調研

在作業設計器中,實用哪種作業工作流的引擎是最主要的,現在對AzkabanOozie進行調研。

一.Azkaban介紹

Azkaban是一個類似於Oozie的任務調度系統,它以flow爲執行單位進行調度,flow爲預定義好的一個或者多個有依賴關係的Job工作流。同時它兼容所有的Hadoop版本,使用Web界面追蹤每個任務的執行情況並且提供了郵件的支持。

Azkaban主要有三個組件組成:

名稱

作用

Mysql

項目以及執行計劃(所有任務的屬性信息、執行計劃、執行的結果以及輸出),每次執行情況等信息

Web服務器

使用jetty做爲web容器,提供服務

Executor執行服務器

負責具體的工作流的提交和執行,可以提交啓動多個執行服務器,他們通過mysql進行協調任務執行。

 

下面將通過Azkaban提供的solo(類似於單例模式)模式,對其提交和執行工作流做測試。

二.執行工作流流程

入下圖所示,爲Azkaban的操作主頁面。

 

經過調研,Azkaban可以調度的任務類型有:shell命令,Java程序,MRSparkHive。下面將通過對以上幾類任務進行調度過程調研

2.1 shell語言工作流

創建工程:

一個工程包含一個或者多個flows,一個flows包含多個jobjob是在Azkaban中運行的一個進程,一個job可能依賴於別的job,多個job和他們之間的依賴組成圖表稱爲flow

Job創建:

只要創建一個以.job爲結尾的文本文件就可以,例如:

 

這種typecommand,告訴Azkaban使用linux的命令或者shell腳本去執行。這是一個job,如果是多個job我們可以定義flow

Flow創建:

定義多個job以及job之間的依賴就可以組成flow。定義依賴可以使用dependencies參數就可以了。例如創建了4job

start.job

type=command

command=sleep 5

command.1=echo "start execute"

test.job

type=command

command=sleep 3

command.1=echo "Hello World"

sleep.job

type=command

dependencies=test, start

command=sleep 10

finish.job

type=command

dependencies=sleep

command=sleep 10

在以上4job中,第三個sleep.job是依賴於teststart.job。也就是sleepjob執行順在需要等待teststart兩個job執行完成。同理finish依賴於sleepfinishi.jobsleep執行成功後再進行。

將這4.job文件打包成zip文件上傳至Azkaban服務器(目前Azkaban只支持zip格式的文件上傳)。之後會生成job之間的關係以及一張DAG flow圖。

 

 

當點擊執行任務後,會依次執行節點並且記錄節點的運行情況。

 

其中會記錄每個job的運行情況以及job的輸出。

 


2.2 MRSpark任務執行

同理Shell任務的job執行次序,底層修改只是調用不同的shell語句進行執行。例如使用spark做爲測試。

首先寫好一個job文件:

type=command

command=spark-submit --master spark://10.2.216.33:7077 --class com.test.AzkabanTest testSparkAzkaban.jar

將文件與測試的testSparkAzkaban.jar進行打包zip格式。上傳至服務器。運行成功後jobLogs會打印如下結果:

 

同理MR Jobjar包以及輸出的文件也可以放在HDFS中,通過shell語言進行。

三.執行的任務類型

Azkaban的使用方式是按照job文件描述來進行使用的,使用type來執行執行任務的類型,通過dependencies可以用來連接任務,即dependencies=A,只有A任務執行完了纔可以執行改任務

其執行任務的類型有:

1.Shell語言類型,在上面已經有相應的解釋。

2.Java文件:使用JavaHadoopJava兩種類型。這兩種是插件形式操作java作業,統一要求的是操作從run方法進行執行,而不是main方法。

3.Hive.

Type=hive

User.to.proxy=azkaban

Azk.hive.action=execute.query

Hive.query.01=sql

四.Azkaban的執行缺陷

由於Azkaban中的每個job都是一個進程,在Azkaban中判斷job成功與否是根據這個進程是否成功執行完成,但是在MR 或者Spark Job執行的過程中,如果代碼出錯,運行在集羣上的任務會停止,並不會有內容寫入目標文件中,此時返回給Azkaban的進程是執行成功的,也就是job節點執行成功。這與任務執行的結果相悖。

例如:

 

在執行某個jar包的過程中時,出現了NullPointException,此時MR作業停止,但是最終Process 顯示的爲執行成功。並且節點最終執行的結果也爲成功:

 

所以爲了防止依賴的節點出現錯誤,其以下節點仍可運行的情況。需要換一個校驗job是否正確執行的維度進行評判,比如檢測MR 或者 Spark 任務的log文件是否正確執行等,或者檢測集羣中的任務是否執行成功。

總結:在執行結束後可以返回hdfs中查詢是否有對應的文件生成,如果有則表示成功,沒有則表示失敗。

五.Azkaban的源碼閱讀

首先從客戶端發送請求入手,客戶端會將所有任務封裝job防止在zip中,其主要邏輯爲:

1.調用LoginAbstractAzkabanServlet。如果是執行任務,會調用其子類ExecutorServlet中的handleAjaxAction。方法。其中會生成一個ExecutableFlow,這個對象中包含了整個工作流的基本信息。

2.生成了exeFlow之後調用executorManager用於提交任務。在這個任務中,會對exeFlow進行資源加鎖,填充exeFlow的屬性後會上傳該工作流的信息到數據庫中。最後調用dispatch 調度任務。

3.最終經過重重調用會生成一個ExecutorApiClient作爲RestClientAzkaban發送任務請求。PS.發送的請求是GET請求。傳輸了一個任務的id。所以以上的所有對exeFlow的操作都是存儲與本地的操作。

 

 

在服務器端,主要的AzkabanServer包含以下屬性:

使用Socket連接的Server以及一個隊列線程池。QueuedThreadPool

1.剛剛在客戶端發送的請求是一個Get請求,所以操作是使用doGet方法。該方法中調用handleAjaxExecute

2.此方法中調用FlowRunnerManager.submitFlowflowId),在服務器端根據flowId從數據庫中獲取了指定的flow

3.根據flow以及相關配置信息會生成一個FlowRunner線程,將此線程放置在線程池中進行執行。其中會使用遞歸找出所有Ready的節點進行執行。在該線程中會在run()方法中不斷執行用戶需要的command

在該方法中會封裝command成一個AzkabanProcess繼承了process類,調用start()方法去執行相關的命令。

 

PS  所以在Azkaban中無論執行hadoop還是spark 任務都可以通過設置命令來執行。但是這些命令操作是在Azkaban的服務器上進行的,由於每次操作一條command會生成一個進程去處理,進程量大很可能會影響到服務器的工作。

同時如果直接將command交給執行的用戶去執行,可能會出現安全問題。而且對於非技術同學操作困難很大。所以未來如果使用Azkaban進行開發時,需要分析用戶的操作生成command,不要將編輯command的入口交給用戶。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章