Hadoop 的 Oozie 工作流管理引擎的實際應用(一)

        Apache Oozie 是 Apache Hadoop 生態系統中的一個關鍵組件,它使得開發人員能夠調度電子郵件通知方面的重複作業,或者調度使用 Java™、UNIX Shell、Apache Hive、Apache Pig 和 Apache Sqoop 等各種編程語言編寫的重複作業。本文將介紹處理某些業務場景的框架的實際應用,還將談論解決方案架構師、技術架構師、顧問、數據科學家、技術領導,以及致力於大數據技術或對大數據技術感興趣的開發人員等方面的話題。

Surajit Paul, Hadoop 顧問, Autodesk Inc.

2015 年 1 月 13 日

  • expand內容

簡介

Apache Oozie 是用於 Hadoop 平臺的一種工作流調度引擎。該框架(如圖 1 所示)使用 Oozie 協調器促進了相互依賴的重複工作之間的協調,您可以使用預定的時間或數據可用性來觸發 Apache Oozie。您可以使用 Oozie bundle 系統提交或維護一組協調應用程序。作爲本練習的一部分,Oozie 運行了一個 Apache Sqoop 作業,以便在 MySQL 數據庫中的數據上執行導入操作,並將數據傳輸到 Hadoop 分佈式文件系統 (HDFS) 中。可以利用導入的數據集執行 Sqoop 合併操作,從而更新較舊的數據集。通過利用 UNIX shell 操作,可從 MySQL 數據庫中提取用來執行 Sqoop 作業的元數據。同理,可執行 Java 操作來更新 Sqoop 作業所需的 MySQL 數據庫中的元數據。

InfoSphere BigInsights Quick Start Edition

InfoSphere BigInsights Quick Start Edition 是一個免費的、可下載的 InfoSphere BigInsights 版本,是 IBM 基於 Hadoop 的產品。使用 Quick Start Edition,您可以嘗試使用 IBM 開發的特性來提高開源 Hadoop 的價值,這些特性包括 Big SQL、文本分析和 BigSheets。爲了讓您的體驗儘可能順利,我們提供了引導式學習,包括一些按部就班的、自定進度的教程和視頻,它們可以幫助您開始讓 Hadoop 爲您工作。沒有時間或數據的限制,您可以自行安排時間在大量數據上進行試驗。觀看視頻遵循這些教程 (PDF) 並 立刻下載 BigInsights Quick Start Edition

圖 1. Oozie 編排架構
MySQL 負責輸入,Oozie 負責處理,HDFS 負責獲取結果

需要安裝的軟件

要想充分利用本文的示例,訪問以下軟件可能對您有所幫助:

該集羣是一個分佈式集羣,在 1 個主名稱節點、2 個核心節點和 8 個任務節點中運行。

Oozie 工作流

Oozie 工作流是控制依賴有向非循環圖 (DAG) 中安排的 Oozie 操作的集合。控制依賴(Control dependency)可確保以下操作在前面的操作已成功完成後纔會啓動。本文首先會簡要概述工作流控制節點,然後重點介紹以下工作流操作節點:

工作流控制節點

啓動控制節點(如清單 1 所示)是工作流作業的入口點。在工作流啓動時,它會自動過渡到啓動過程中指定的節點。

清單 1. 啓動控制節點
<workflow-app xmlns="uri:oozie:workflow:0.2" name="ooziedemo-wf">
    <start to="timeCheck"/>
</workflow-app>

末端控制節點(如清單 2 所示)是結束工作流作業時所用的節點。它表示工作流操作已經成功完成。一個工作流定義必須有一個末端節點。

清單 2. 末端控制節點
<workflow-app xmlns="uri:oozie:workflow:0.2" name="ooziedemo-wf">
    <end name="end"/>
</workflow-app>

停止控制節點(如清單 3 所示)可使工作流作業自行停止。在到達停止節點(kill node)時,如果工作流作業啓動的一個或更多操作正在運行,那麼當前運行的所有操作都將停止。工作流定義可以包含零個或更多停止節點。

清單 3. 停止控制節點
<workflow-app xmlns="uri:oozie:workflow:0.2" name="ooziedemo-wf">
    <kill name="fail">
        <message>Sqoop failed, error message[${wf:errorMessage(wf:lastErrorNode())}]</message>
   </kill>
</workflow-app>

決策控制節點(如清單 4 所示)可使工作流確定要採用的執行路徑。決策節點的工作原理類似於擁有一組謂詞轉換對(predicates-transition pair)和一個默認轉換的 switch-case 塊。謂詞是按順序進行評估的,直至其中一個評估爲 ture 爲止,同時還會進行相應的轉換。如果沒有一個謂詞被評估爲 true,則會採用默認轉換。

清單 4. 決策控制節點
<workflow-app xmlns="uri:oozie:workflow:0.2" name="ooziedemo-wf">
    <decision name="master-decision">
       <switch>
         <case to="sqoopMerge1">
                 ${wf:actionData('hiveSwitch')['paramNum'] eq 1}
         </case>
         <default to="sqoopMerge2"/>
       </switch>
   </decision>
</workflow-app>

分支節點 將一個執行路徑分爲多個併發路徑。聯接節點 一直等待,直到前面的分支節點的所有併發執行路徑都到達聯接節點爲止。您必須成對使用分叉節點和聯接節點,如清單 5 所示。

清單 5. 分支-聯接控制節點
<workflow-app xmlns="uri:oozie:workflow:0.2" name="ooziedemo-wf">
    <fork name="forking">
        <path start="sqoopMerge1"/>
        <path start="sqoopMerge2"/>
    </fork>
    <join name="joining" to="hiveSwitch"/>
</workflow-app>

Oozie shell 操作

您可以將 Oozie shell 操作作爲工作流的一部分進行配置,從而運行某個文件中的一組 shell 腳本。您可以利用包含必要參數的 job-trackername-node 和 exec 元素來配置 Oozie shell 操作,從而執行相關的任務,如清單 6 所示。您可以將具有配置參數的一個配置 shell 操作來創建或刪除 HDFS 上的文件和目錄,然後啓動 shell 作業。您可以使用與配置元素內聯的 job-xml 元素,利用配置參數將一個 XML 文件傳遞給 shell 作業。您可以配置其他文件或歸檔文件,讓它們可用於 shell 作業。在 shell 作業結束後,您可以讓 shell 作業的輸出可供workflow 作業使用,但它需要滿足以下條件:

  • 輸出的格式必須是一個有效的 Java 屬性文件。
  • 輸出的大小必須小於 2KB。
清單 6. Shell 腳本
host="XXX.XX.XX.XXX"
port="3306"
username="root"
password=""
database="zzz"
tableName="$1"

####################################
echo "Host: $host"
echo "Database: $database"
echo "Table: $tableName"
####################################

sqoopLstUpd=`mysql --host=$host --port=$port --user=$username --password=$password 
-N -e 'SELECT PARM_DATE_VAL from T_CONTROL_PARM where PARM_NM="SQOOP_INCR_LST_UPD"
 and PARM_GROUP_NM="'$tableName'"' $database`

echo "sqoopLstUpd=$sqoopLstUpd"
echo "tableName=$tableName"

清單 7 展示了 workflow.xml 文件中的 shell 操作配置。

清單 7. Oozie shell 操作
<action name="timeCheck">
    <shell xmlns="uri:oozie:shell-action:0.1">
       <job-tracker>${jobTracker}</job-tracker>
       <name-node>${nameNode}</name-node>
       <configuration>
           <property>
               <name>mapred.job.queue.name</name>
               <value>${queueName}</value>
           </property>
       </configuration>
       <exec>${sqoopUpdTrack}</exec>
       <argument>${tableName}</argument>
       <file>${sqoopUpdTrackPath}#${sqoopUpdTrack}</file>
       <capture-output/>
    </shell>
    <ok to="sqoopIncrImport"/>
    <error to="fail"/>
</action>

要想訪問 shell 輸出,可以使用清單 8 中所示的 Sqoop 增量作業。

清單 8. 用來實現增量導入的 Oozie Sqoop 操作
<action name="sqoopIncrImport">
        <sqoop xmlns="uri:oozie:sqoop-action:0.2">
           <job-tracker>${jobTracker}</job-tracker>
           <name-node>${nameNode}</name-node>
           <prepare>
               <delete path="${s3BucketLoc}/${tableName}/incr"/>
               <mkdir path="${s3BucketLoc}/${tableName}"/>
           </prepare>
           <configuration>
               <property>
                   <name>mapred.job.queue.name</name>
                   <value>${queueName}</value>
               </property>
           </configuration>
           <arg>import</arg>
           <arg>--connect</arg>
           <arg>${dbURL}</arg>
           <arg>--driver</arg>
           <arg>${mySqlDriver}</arg>
           <arg>--username</arg>
           <arg>${user}</arg>
           <arg>--table</arg>
           <arg>${wf:actionData('timeCheck')['tableName']}</arg>
           <arg>--target-dir</arg>
           <arg>${s3BucketLoc}/${tableName}/incr</arg>
           <arg>--check-column</arg>
           <arg>LAST_UPD</arg>
           <arg>--incremental</arg>
           <arg>lastmodified</arg>
           <arg>--last-value</arg>
           <arg>${wf:actionData('timeCheck')['sqoopLstUpd']}</arg>
           <arg>--m</arg>
           <arg>1</arg>
       </sqoop>
       <ok to="sqoopMetaUpdate"/>
       <error to="fail"/>
   </action>

Oozie Java 操作

Java 操作運行了指定的主要 Java 類的 public static void main (String [] args) 方法。Java 應用程序作爲具有單個 mapper 任務的 MapReduce 作業運行在 Hadoop 集羣上。工作流作業一直要等到 Java 操作結束運行之後才能繼續執行下一個操作。Java 操作可使用 job-trackername-node、Java 主類、JVM 選項和輸入參數進行配置,如清單 9 所示。您可以使用 Expression Language (EL) 表達式將參數分配給內聯屬性值。您必須以 Java 屬性文件的格式寫入所有輸出參數。

您可以配置 Java 操作來清理 HDFS 文件和目錄,或者建立 Apache HCatalog 分區,然後再啓動 Java 應用程序。這使得 Oozie 能夠在出現暫時性或非暫時性故障時重試 Java 操作。

清單 9. Oozie Java 操作
<action name="sqoopMetaUpdate">
          <java>
               <job-tracker>${jobTracker}</job-tracker>
               <name-node>${nameNode}</name-node>
               <configuration>
                   <property>
                      <name>mapred.job.queue.name</name>
                      <value>${queueName}</value>
                   </property>
               </configuration>
               <main-class>SqoopMetaUtil</main-class>
               <java-opts></java-opts>
               <arg>${tableName}</arg>
               <archive>${mySqlDriverPath}</archive>
          </java>
          <ok to="hiveSwitch"/>
          <error to="fail"/>
</action>

您可以通過使用 capture-output 來配置 Java 操作,從而將值傳遞給下一操作。您可以通過使用 Hadoop EL 函數來訪問這些值。您能夠以 Java 屬性文件的格式在 Java 類中寫入值,如清單 10 所示。

清單 10. 用於實現值傳遞的 Java 代碼片段
String OOZIE_ACTION_OUTPUT_PROPERTIES = "oozie.action.output.properties";
String oozieProp = System.getProperty(OOZIE_ACTION_OUTPUT_PROPERTIES);
       OutputStream os = null;
       if(oozieProp != null){
          File propFile = new File(oozieProp);
          Properties p = new Properties();
          p.setProperty("name", "Autodesk");
          p.setProperty("address", "Sun Rafael");
          try {
               os = new FileOutputStream(propFile);
               p.store(os, "");
          } catch (FileNotFoundException e) {
               System.err.println("<<< FileNotFoundException >>>"+e.getMessage());
          } catch (IOException e) {
               System.err.println("<<< IOException >>>"+e.getMessage());
          }
          finally{
               if(os != null)
               try {
                    os.close();
               } catch (IOException e) {
                    System.err.println("<<< IOException >>>"+e.getMessage());
               }
          }
       }
       else{
            throw new RuntimeException(OOZIE_ACTION_OUTPUT_PROPERTIES
                    + " System property not defined");
    }

您可以在 workflow.xml 文件中配置操作來訪問屬性文件中的相應值設置,如清單 11 所示。

清單 11. 用於實現值傳遞的 Oozie Java 操作
<action name="jProperties">
      <java>
           <job-tracker>${jobTracker}</job-tracker>
           <name-node>${nameNode}</name-node>
           <configuration>
               <property>
                  <name>mapred.job.queue.name</name>
                  <value>${queueName}</value>
               </property>
           </configuration>
           <main-class>PropertyExplorer</main-class>
           <java-opts></java-opts>
           <capture-output/>
      </java>
      <ok to="email"/>
      <error to="fail"/>
   </action>

   <action name="email">
         <email xmlns="uri:oozie:email-action:0.1">
            <to>[email protected]</to>
            <subject>Oozie workflow finished successfully!</subject>
            <body>${wf:actionData('jProperties')['name']} | 
            ${wf:actionData('jProperties')['address']}</body>
         </email>
         <ok to="end"/>
         <error to="fail"/>
   </action>

Oozie Sqoop 操作

Oozie 工作流觸發了一個 Sqoop 腳本,該腳本在 Hadoop 集羣上啓動了一個 Sqoop 作業。Sqoop 作業通過在 Hadoop 集羣上啓動 MapReduce 作業來完成任務。Sqoop 腳本啓動的 MapReduce 作業會將數據從 RDBMS 傳輸到 HDFS。您可以配置一個 Sqoop 操作(如清單 12 所示)來刪除 HDFS 上的文件和目錄,然後再啓動 Sqoop 作業。與其他 Oozie 操作類似,您可以通過使用 job-xml 元素,利用其他的屬性來配置 Sqoop 操作。configuration 元素中指定的屬性值將會覆蓋 job-xml 元素中指定的屬性。可以將其他文件和歸檔文件提供給 Sqoop 作業。

清單 12. 用於合併的 Oozie Sqoop 操作
<action name="sqoopMerge1">
         <sqoop xmlns="uri:oozie:sqoop-action:0.2">
             <job-tracker>${jobTracker}</job-tracker>
             <name-node>${nameNode}</name-node>
             <prepare>
                 <delete path="${s3BucketLoc}/${tableName}/master1"/>
                 <mkdir path="${s3BucketLoc}/${tableName}"/>
             </prepare>
             <configuration>
                 <property>
                     <name>mapred.job.queue.name</name>
                     <value>${queueName}</value>
                 </property>
             </configuration>
             <arg>merge</arg>
             <arg>--new-data</arg>
             <arg>${s3incr}</arg>
             <arg>--onto</arg>
             <arg>${s3BucketLoc}/${tableName}/master2</arg>
             <arg>--target-dir</arg>
             <arg>${s3BucketLoc}/${tableName}/master1</arg>
             <arg>--jar-file</arg>
             <arg>${tableJarLoc}/${tableName}.jar</arg>
             <arg>--class-name</arg>
             <arg>${tableName}</arg>
             <arg>--merge-key</arg>
             <arg>ROW_ID</arg>
         </sqoop>
         <ok to="hive-master1"/>
         <error to="fail"/>
   </action>

Oozie Hive 操作

您可以配置 Hive 操作(如清單 13 所示)來執行 HDFS 上的文件和目錄中的任何 Hive 腳本。該操作啓動了一個 MapReduce 作業來完成這些任務。您需要在 Oozie 上配置 Hive 操作,使用 Hive 配置文件 hive-default.xml 或 hive-site.xml 作爲 job-xml 元素。對於支持 Hive 訪問 Oozie 環境而言,這一點是必需的。您可以配置 Hive 操作來創建或刪除 HDFS 文件和目錄,然後再啓動 Hive 作業。configuration 元素中指定的屬性值將會覆蓋 job-xml 文件中指定的值。您可以添加其他的文件和歸檔文件,讓它們可用於 Hive 作業。Oozie 執行了由腳本元素中的路徑指定的 Hive 腳本。您可以通過 Oozie 工作流,將參數作爲輸入參數分配給 Hive 腳本。

清單 13. Oozie Hive 操作
<action name="hiveSwitch">
     <shell xmlns="uri:oozie:shell-action:0.1">
         <job-tracker>${jobTracker}</job-tracker>
         <name-node>${nameNode}</name-node>
          <configuration>
          <property>
              <name>mapred.job.queue.name</name>
              <value>${queueName}</value>
          </property>
          </configuration>
          <exec>${hiveSwitchScript}</exec>
          <argument>${tableName}</argument>
          <file>${hiveSwitchScriptPath}#${hiveSwitchScript}</file>
       <capture-output/>
       </shell>
       <ok to="master-decision"/>
       <error to="fail"/>
   </action>

Oozie 電子郵件操作

Oozie 電子郵件操作(如清單 14 所示)可以從工作流應用程序發送電子郵件。除了主題和消息正文之外,電子郵件操作還必須擁有 to 和 cc(可選)地址。您可以使用逗號分割的電子郵件地址向多個收件人發送電子郵件。電子郵件操作可同步運行,而工作流作業一直要等到發送電子郵件之後纔會觸發下一個操作。您可以使用 Hadoop EL 表達式將參數分配給電子郵件操作。

清單 14. Oozie 電子郵件操作
<action name="email">
  	<email xmlns="uri:oozie:email-action:0.1">
            <to>[email protected]</to>
            <subject>Oozie workflow finished successfully!</subject>
            <body>${wf:actionData('jProperties')['name']} | 
            ${wf:actionData('jProperties')['address']}</body>
        </email>
        <ok to="end"/>
        <error to="fail"/>
   </action>

結束語

當多個相互依賴的作業與數據流捆綁在一起的時候,Oozie 工作流就會變成一個數據管道應用程序。Apache Oozie 工作流促進了數據邏輯流程的設計、錯誤處理、故障轉移機制等。您可以配置 Oozie 協調器或捆綁的應用程序來有效地管理工作流,不過,關於這些主題的討論已超出了本文的討論範圍。一些等效的 Hadoop 工作流引擎包括 Amazon Data Pipeline、Simple Workflow Engine、Azkaban、Cascading 和 Hamake。雖然 Hamake 和 Oozie 是基於 XML 的配置,但 Azkaban 是使用包含鍵值對的文本文件進行配置的,而 Cascading 是使用 Java API 進行配置的。

http://www.ibm.com/developerworks/cn/data/library/bd-hadoopoozie/


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