Oozie和Azkaban的技術選型和對比

OozieAzkaban的技術選型和對比

一.AzkabanOozie的工作流程

1.1 Azkaban工作流程

Azkaban將需要操作的信息打包成zip文件發送給Server端,Server對用戶的信息進行存儲。用戶在Web UI 或者通過HTTP Client發送操作請求後,Server會根據用戶定義的*.job文件(KV 匹配),執行zip包中的Jar文件。

源碼的執行過程:

 

1.從Web頁面提交工作流程:

Method.GET

/executor?projectId=33&project=testSpark&ajax=executeFlow&flow=test1&disabled=%5B%5D&failureEmailsOverride=false&successEmailsOverride=false&failureAction=finishCurrent&failureEmails=&successEmails=¬ifyFailureFirst=false¬ifyFailureLast=false&concurrentOption=ignore

 

用戶提交任務後,發送任務的詳情到服務器中,Azkaban客戶端會對任務以及用戶的信息進行校驗,封裝後首先將執行的信息(任務,時間,用戶等)存入數據庫中(表active_executing_flows),之後執行dispatch方法,對需要執行的任務流進行調度。

dispatch方法中,首先會更新executions_flows表,然後將操作的語句發送到指定的ip和端口進行執行。

 

2.服務器接收到了請求:如果是執行操作那麼接收到的actiontypeexecute。接着服務器會從數據庫中獲取相應的工作流flow,服務器將flow封裝成FlowRunner

FlowRunner的屬性

 

ExecutorService

線程池對象

ExecId

從數據庫中獲取相應的flow

numJobThreads

默認10個線程

JobTypeManager

定義Job的插件,有以下幾種插件

 

Set<JobRunner>

將有向無環圖中的node抽象成一個JobRunner進行運行

其中任務的執行是使用一個遞歸操作runReadyJob(),循環操作其中的node,也就是每個JobRunner

JobRunner的主要屬性:

Job

執行任務的父類接口。

JobtypeManager

根據輸入的type類型返回此節點需要執行的任務類型

JobId

唯一標識符

配置文件,Job的路徑,監控FlowWatch.....

 

其中會根據需要操作的Flow來定義Jobtype。返回相應的類型。例如MR  返回的是JavaProcessJob

也就是說:每一個節點,是通過新建一個進程去運行。在這個進程中會執行多條command,通過process.run(),運行用戶定義的job

PS.每條command都需要重新建立一個process

 

1.2  Oozie工作流程

Oozie中,用戶需要準備以下文件:

Job.properties

Job文件存儲HDFSResourceManager的配置

Workflow.xml

配置每個節點之間的依賴關係

Lib

存放着指定運行jar的關聯包

.jar

運行的jar

 

用戶需要將這些文件放置在一個文件夾下,然後上傳至HDFS中。在客戶端或者終端中發送請求去執行。

源碼執行流程:

使用控制行操作:

1.首先調用:org.apache.oozie.cli.OozieCLI。首先根據不同的command類型調用不同的發送請求,例如使用MRCommand

 

在這個方法中會生成一個ClientSubmit指定的Properties(根據ClientCommand生成)。提交的對象是HTTPJobSubmit。調用該對象中的call方法和Server進行通信。最終返回一個jobIdMETHOD.POST

 

2.服務器端:首先調用相應的Servlet,調用提交作業方法,生成一個DAG圖(DAGEngine,然後所有的操作都是基於DAG來實現的)。

A.如果我們在提交一個作業時生成了jobType那麼,此時會選定不同的提交類型(類似於一個工廠模式),返回指定的信息。

B.首先它會調用SubmitXCommand.call()方法,將job的信息加入數據庫中並且返回一個jobId

C.之後執行start(jobId)的方法,調用Xcommand.call()方法,生意Instrument對任務進行監控,在這個方法中會調用一個SignalXCommand.execute()方法。

Oozie的後端中會維護一個異步隊列,在上述的execute中會根據job中的每一個action的類型,去生成相應的Command加入異步隊列中。類型如下:

skipAction

SignXcommand

startAction

ActionStartXCommand

ForkAction

ActionStartXCommand 和上面的jobType不同

類似還有killActionXCommandworkflowNotifyActionXCommand

PS如果是MR 或者 Spark  映射ActionStartXCommand 類型。

D.在後端異步隊列CallableQueueService中。(在這個方法中使用InstrumentJava進行進行監控)。會調用這些XCommandexecute方法,不同的類型會實例化不同的executor,例如MR Spark都會實例化JavaActionExecutor(同時還有SubWorkflowActionExecutor執行提交任務)。

E.在上述對象的execute方法中會根據配置生成JobClient,來獲取正在運行的Running Job的信息以及提交Job  SubmitJob,返回一個jobId。如果獲取正在運行的runningJob在這個對象中還有job.trackerUrl也就是任務的日誌。可以供以後展示。

 

 

測試用例提交流程:

 

看測試用例提交Hadoop作業中,首先對連接進行驗證,然後每次提交會生成一個JobClient,該Oozie作爲一個ClientHadoop服務器發送操作job的請求。

 

其中操作hive hadoop spark 作業均是JavaActionExecutor,該執行器中會調用submitLauncher提交Hadoop作業。

1.3  小結

Azkaban的工作流運行是依靠操作進程來提交不同的命令的,它操作任務成功和失敗的信息在於進程的相應,但是這並不能有效的管理任務的成功與失敗。

Oozie 執行MR 任務是依靠HadoopJar包,以Server作爲Client發送請求至集羣進行操作。在此之前需要將任務所依賴執行的jar包上傳至HDFS中才可執行。

通過了解OozieAzkaban的執行過程,個人任務使用Oozie作爲底層的流程引擎比較合適,因爲通過JobClient可以有效的監控正在執行的任務,獲取任務的信息,如果使用Azkaban則只能獲取進程執行的詳情。

 

二.workflow.xml配置工作流流程

Oozie中每個工作流有不同的狀態,具體如下:

PERP

工作流已經被定義但是沒有執行

RUNNING

當一個工作流開始執行。它不會達到結束的狀態只會出錯結束或者掛起

SUSPENDED

工作流給掛起狀態從RUNNING狀態過來

SUCCESSED

工作流到達END節點

KILLED

工作流處於RUNNINGSUSPENDED狀態被殺死

FAILED

工作流遇到錯誤停止

 

工作流節點有以下幾種類型:

控制流節點:控制工作流開始和結束以及控制執行的路徑

Start

<start to="[NODE-NAME]" />

第一個執行的節點

End

<end name="[NODE-NAME]" />

執行到該節點任務成功,一個工作流只能有一個end

Kill

<kill name="[NODE-NAME]">

<message>[MESSAGE-TO-LOG]</message>

</kill>

被殺死節點的名稱和備註,達到該節點時,任務狀態爲KILLED

Decision

<decision name="[NODE-NAME]">

<switch>

<case to="[NODE_NAME]">[PREDICATE]</case>

<default to="[NODE_NAME]" />

</switch>

</decision> 工作流執行到此處時會根據條件進行判斷,滿足條件的路徑將被執行

Fork

<fork name="[FORK-NODE-NAME]">

<path start="[NODE-NAME]" />...

</fork> 多個併發路徑

Join

<join name="[JOIN-NODE-NAME]" to="[NODE-NAME]" />

Fork的多條路徑會在Join處匯合,只有所有路徑都到了,纔會執行join.

 

動作類型節點:能夠觸發一個計算任務或者處理任務執行的節點。該類節點有以下的基本特性:

1.異步:Oozie會啓動一個異步隊列來執行某個工作流job,並通過回調機制以及輪詢來獲取任務的執行狀態.

2.節點要麼成功要麼失敗。

3.一個任務如果在某個節點失敗了,那麼Oozie提供一套恢復運行的策略,如果是狀態轉移失敗,那麼自動運行,否則需手動運行。

動作類節點主要有以下幾大類:

MR

<action name="[NODE-NAME]">

<map-reduce>...啓動一個MRJOB的執行,並且可以配置其中的其他任務,如streaming,pipes,file,archive

Hive

<hive xmlns="uri:oozie:hive-action:0.2">

<script>[HIVE-SCRIPT]</script>

<param>[PARAM-VALUE]</param>

執行hive查詢sql

Sqoop

<sqoop xmlns="uri:oozie:sqoop-action:0.2">

Pig

啓動腳本實現Job

Fs

<fs>

<delete path='[PATH]' />

<mkdir path='[PATH]' />

<move source='[SOURCE-PATH]' target='[TARGET-PATH]' />

....

</fs>  操作HDFS

Java

OozieJava是有main方法執行的程序,他在服務器中以MR Job進行執行,這個Job只有一個Map程序,需要執行

namenode,jobTracker以及JVM和傳輸給主函數的參數

Sub-workflow

子流程動作,主流程執行過程中,遇到子流程點執行時,會一直等到子流程執行完後才跳轉到下一個要執行的節點。

Shell

<shell xmlns="uri:oozie:shell-action:0.2">

<exec>[SHELL-COMMAND]</exec>

<argument>[ARGUMENT-VALUE]</argument>

執行shell語句

 

三.Oozie根據xml執行job

3.1新建workflow

可以根據hue中的方法進行新建,重寫hue中的editor/workflow/new方法,不過得將pythonjava

3.2執行workflow

參考oozie中的提交作業的流程,看下操作的主要對象的屬性信息:

WorkflowJobBean

startTimestamp

開始時間

endTimestamp

結束時間

app_path

jar包位置

Conf

配置文件的信息BLOB二進制大文件

Actions

List<WorkflowActionBean> 一系列的執行節點

等等。。

 

這個是一個任務的基本屬性,主要包含了一堆actions節點和conf配置文件。在提交代碼的過程中,以MR 作業爲例:

首先,在提交的過程中,會將用戶的任務信息封裝成一個workFlowJob以及workflowInstancejob的狀態,執行路徑等)並判斷job的行爲狀態。

然後,對這個Job中的每個action進行遍歷,判斷action屬於哪種類型,然後放入後端的異步隊列中。

異步隊列會執行其中每一個action,執行時生成一個executor,這個執行器在操作的過程中會根據每一個actionxml文件生成org.apache.hadoop.conf.configuration actionConfig對象,循環遍歷每個action的節點xml映射去填充這個對象的屬性。

最終根據actionConf生成一個jobClient,發送用戶的請求。

 

四.如何運行Spark作業

4.1 Oozie

Oozie中對spark作業的執行有其自定義的一套執行器----sparkActionExecutor,這個執行器繼承了JavaActionExecutor

在這個執行器中,主要作用是定義好spark作業的配置信息以及在生成Client的時候定義的Configuration actionConfig對象的初始化。

也就是說,spark對象會根據不同的配置初始化相應的JobClient用於發送spark任務jar包,其具體的流程和HadoopActionExecutor相似,都是調用JavaActionExecutorexecute()方法。

4.2 Azkaban

Azkaban的底層是將命令封裝成一個進程進行執行,在這個過程中我們可以自定義相關命令。發送jar包進行執行。

4.3 小結

如果從操作的角度上來說,那麼Azkaban直接上傳jar包然後執行,其過程更爲簡易,並且用戶操作相對於Oozie來說更爲簡單,困難在於,不能直接將所需要操作的shell語句編寫入口提供給用戶。需要根據WEB UI的返回值,生成操作命令。

Oozie的配置相對於複雜,但是它已經提供了一套相對於比較完整的WEB 頁面接口以及HUE中配置workflow.xml的代碼。困難點在於將用戶編寫的操作流程以xml形式形象的展示出來。

 

五.OozieAzkaban如何判斷任務是否完成

5.1 Oozie判斷任務是否完成

如果任務正在運行的過程中,那麼當前這個任務會被存儲在數據庫中,並且狀態標記爲RUNNING。當任務在執行的過程中,如果不出錯且不出現掛起的狀態,則任務狀態不會變化。

當任務操作結束後(無論錯誤還是成功執行完成),Oozie會操作回調接口,具體操作流程如下:

1.生成CompletedActionXCommand,封裝當前action的信息。

2.在這個對象的execute方法中,如果當前action的狀態爲PREP,則將繼續輪詢,會將輪詢的命令加入執行的異步隊列中,並設置相應的延時執行。

3.如果任務正處於RUNNING中,那麼會在異步隊列中加入ActionCheckXCommand對象,在這其中例如使用MR,則會生成JavaActionExecutor 類型的執行器。

4.執行這個執行器中的check方法。根據jobId生成jobClient獲取HADOOP中正在運行的RUNNING JOB

5.如果job.isComplete(),會判斷任務是否結束。結束是否運行成功,有相應接口。(判斷成功與否包括org.apache.hadoop.mapred.Counters)代碼位於:

/oozie/action/hadoop/LauncherMapperHelper/isMainSucessful。成功返回SUCCESSED,失敗FAILED

6.如果任務未結束,則任務設置爲RUNNING

最終每次jobClient查詢結束需要close()Oozie會將每次運行的狀態信息存儲於數據庫中。

 

5.2Azkaban判斷任務是否完成

Azkaban在提交任務之後會在Client運行一個Process,不斷的向Server發送查詢請求。發送的請求:

/executor?execid=55&ajax=fetchexecflowupdate&lastUpdateTime=1470735951842

ServerAzkaban會維護一個ConcurrentHashMap存儲着執行的flow。這個hashmap是放在內存中的。由於Azkaban操作的顆粒度是進程,進程的執行成功或者失敗都會影響這個hashmap

但是進程的執行結果無法直接反應任務是否執行成功。

六.總結

綜上述的幾點對比Oozie以及Azkaban,個人覺得選擇Oozie作爲流程引擎的選型比較好,理由如下:

1.Oozie是基於Hadoop系統進行操作,而Azkaban是基於命令行進行操作。使用hadoop提供的第三方包JobClient比直接在底層跑shell命令開發成本小,可能遇到的坑也少(一個是基於平臺,一個是基於系統)。

2.Oozie的操作是放在Hadoop中,而Azkaban的運行是服務器運行shell命令。爲保證服務器的穩定,使用Oozie靠譜點。

3.Ooize提供查詢任務執行狀態,Azkaban查詢的是進程執行的結果,如果某進程執行的shell命令出錯,其進程仍展示位成功,混淆了任務輸出。

4.Oozie將任務執行的狀態持久化到數據庫中,Azkaban將任務的狀態存儲在服務器內存中,如果掉電,則Azkaban會丟失任務信息。

5.Ooize中定義的action類型更爲豐富,而Azkaban中的依賴較爲簡單,當面對複雜的邏輯時Oozie執行的比較順暢(網上說的,但是沒有實踐的數據。。。)。

 

Oozie作爲流程引擎的難點:

1.定義workflow.xml的過程,需要保證有效的完成用戶的邏輯且運行的過程中job不出錯。

2.部署有點麻煩。

3.學習的成本會略高。

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