Oozie - 流式排程器
為什麼要有Oozie?
在資料業務場景,對於資料的處理往往是分階段處理,而不同的階段可能採用了不同的技術框架去完成這個業務需求,且可能在不同的階段要幹不同的事。
炒飯(鍋) à 吃飯(碗) à 筷子(動手)
要吃飯就要等炒飯先用鍋炒好,要用筷子動手吃飯就要等碗裡裝了飯,這是一個流水線式的過程,如果用設定時間的方式,到了什麼時候就拿完去裝飯,但如果今天兼職的人特別多,那麼炒的飯必然就多了,時間也長了,但是設定時間到了,還沒炒好,可是有一堆人擠在廚房喊要飯,問題就出現了。
於是有的人會想,如果有一個監督人幫我去這個監控、通知、控制好整個流程,那樣多好啊,廚房就不會給天天催了,也不會發生擁擠的情況。
小結:一個完整的資料分析系統通常是由大量的任務單元組成,Shell指令碼、Java程式、MapReduce程式、Hive指令碼等等,各個任務單元之間存在時間先後及前後依賴關係。
為了很好的組織這樣的複雜執行計劃,需要一個工作流排程系統來呼叫執行。
簡單的工作流排程:Liunx的crontab來定義
複雜的工作流排程:Oozie、Azakaban等。。。
主流幾款工作流排程框架
特性 |
Hamake |
Oozie |
Azkaban |
Cascading |
工作流描述語言 |
XML |
XML (xPDL based) |
text file with key/value pairs |
Java API |
依賴機制 |
data-driven |
explicit |
explicit |
explicit |
是否要web容器 |
No |
Yes |
Yes |
No |
進度跟蹤 |
console/log messages |
web page |
web page |
Java API |
Hadoop job排程支援 |
no |
yes |
yes |
yes |
執行模式 |
command line utility |
daemon |
daemon |
API |
Pig支援 |
yes |
yes |
yes |
yes |
事件通知 |
no |
no |
no |
yes |
需要安裝 |
no |
yes |
yes |
no |
支援的hadoop版本 |
0.18+ |
0.20+ |
currently unknown |
0.18+ |
重試支援 |
no |
workflownode evel |
yes |
yes |
執行任意命令 |
yes |
yes |
yes |
yes |
Amazon EMR支援 |
yes |
no |
currently unknown |
yes |
什麼是Oozie?
Oozie(馴象人)是一個基於工作流引擎的開源框架,由Cloudera公司貢獻給Apache的,用在一個工作流內以一個特定順序執行一組工作或流程。
Oozie在叢集中扮演的是定時排程任務,多工,並開源按照業務邏輯順序排程。
組成
Workflow:順序執行流程節點,執行分支多節點或合併多分點為一個分支。
Coordinator:定時觸發Workflow
BundleJob:繫結多個Coordinator
Oozie節點
控制流節點(Control Flow Nodes):一般都是定義在工作流開始或結束,比如start、end、kill等,以及提供工作流的執行路徑。
動作節點(Action Nodes):執行具體動作的節點。
案例
job.properties
#NameNode地址
nameNode=hdfs://hadoop-senior00-levi.com:8082
#ResourceManager地址,預設埠8032
jobTracker=hadoop-senior00-levi.com:8032
#內部的Event佇列名稱
queueName=default
examplesRoot=oozie-apps
#程式位置
oozie.wf.application.path=${nameNode}/user/${user.name}/${examplesRoot}/shell
#執行這個指令碼
EXEC1=test1.sh
EXEC2=test2.sh
workflow.xml
<workflow-app xmlns="uri:oozie:workflow:0.4" name="shell-wf">
<start to="shell-node1"/>
<action name="shell-node1">
<shell xmlns="uri:oozie:shell-action:0.2">
<job-tracker>${jobTracker}</job-tracker>
<name-node>${nameNode}</name-node>
<configuration>
<property>
<name>mapred.job.queue.name</name>
<value>${queueName}</value>
</property>
</configuration>
<exec>${EXEC1}</exec>
<!-- <argument>my_output=Hello Oozie</argument> -->
<file>/user/admin/oozie-apps/shell/${EXEC1}#${EXEC1}</file>
<capture-output/>
</shell>
<ok to=" shell-node2"/>
<error to="fail"/>
</action>
<action name="shell-node2">
<shell xmlns="uri:oozie:shell-action:0.2">
<job-tracker>${jobTracker}</job-tracker>
<name-node>${nameNode}</name-node>
<configuration>
<property>
<name>mapred.job.queue.name</name>
<value>${queueName}</value>
</property>
</configuration>
<exec>${EXEC2}</exec>
<!-- <argument>my_output=Hello Oozie</argument> -->
<file>/user/admin/oozie-apps/shell/${EXEC2}#${EXEC2}</file>
<capture-output/>
</shell>
<ok to="end"/>
<error to="fail"/>
</action>
<decision name="check-output">
<switch>
<case to="end">
${wf:actionData('shell-node')['my_output'] eq 'Hello Oozie'}
</case>
<default to="fail-output"/>
</switch>
</decision>
<kill name="fail">
<message>Shell action failed, error message[${wf:errorMessage(wf:lastErrorNode())}]</message>
</kill>
<kill name="fail-output">
<message>Incorrect output, expected [Hello Oozie] but was [${wf:actionData('shell-node')['my_output']}]</message>
</kill>
<end name="end"/>
</workflow-app>
test1.sh
#!/bin/bash
/usr/bin/date > /tmp/test.log
test2.sh
#!/bin/bash
/usr/bin/date > /tmp/test.log
執行:
上傳到HDFS:
hdfs dfs -rmr /user/levi/oozie-apps
hdfs dfs -put oozie-apps/ /user/levi
執行任務:
bin/oozie job --oozie http://hadoop-senior00-levi.com:11000/oozie -config oozie-apps/shell/job.properties -run
使用注意事項
- 啟動不了,則到oozie-server/temp檢視是否有*.pid檔案,有就刪除後在啟動。
- 如果無法關閉oozie則kill掉。
- Mysql配置如果沒有生效的話,預設使用derby資料庫
- 在本地修改完成的job配置,必須重新上傳到HDFS。
- Linux使用者名稱和Hadoop的使用者名稱不一致。
- 時區
有興趣可以加QQ群討論:963022008