zoukankan      html  css  js  c++  java
  • 大数据之azkaban与oozie

      当我们要做一个主题分析时,基本上都会有这样一个流程,采集数据,数据预处理,数据入库,数据分析等一系列的操作。但是这些操作往往我们需要布置做一遍,有时候甚至需要定时定点的去做,比如数据采集。当我们每天都需要做一系列的重复的工作时,我们肯定首先就是想到,能不能我只做一遍,剩下的交给一个机器人自动帮我完成或者交给电脑自动帮我完成。

      这时候领克就推出了一款叫做azkaban的工作流调度软件,是开源免费的。我们的Apache基金会呢也有一款开源的工作流调度软件,名为oozie。它俩都是作为工作流调度的软件,都能帮我们实现一系列工作的调度,但是它们之间实现的原理却不太一样。

    Azkaban与Oozie的介绍

      Azkaban是由linkedin(领英)公司推出的一个批量工作流任务调度器,用于在一个工作流内以一个特定的顺序运行一组工作和流程。Azkaban使用job配置文件建立任务之间的依赖关系,并提供一个易于使用的web用户界面维护和跟踪你的工作流。

      Oozie 是一个用来管理 Hadoop生态圈job的工作流调度系统。由Cloudera公司贡献给Apache。Oozie是运行于Java servlet容器上的一个java web应用。Oozie的目的是按照DAG(有向无环图)调度一系列的Map/Reduce或者Hive等任务。Oozie 工作流由hPDL(Hadoop Process Definition Language)定义(这是一种XML流程定义语言)。

    Azkaban与Oozie的原理

      Azkaban:

            

      mysql服务器: 存储元数据,如项目名称、项目描述、项目权限、任务状态、SLA规则等

       AzkabanWebServer:对外提供web服务,使用户可以通过web页面管理。职责包括项目管理、权限授权、任务调度、监控executor。

       AzkabanExecutorServer:负责具体的工作流的提交、执行。

      Oozie:

    Oozie对工作流的编排,是基于workflow.xml文件来完成的。用户预先将工作流执行规则定制于workflow.xml文件中,并在job.properties配置相关的参数,然后由Oozie Server向MR提交job来启动工作流。

    Azkaban与Oozie的安装

      Azkaban:

        Azkaban三种部署模式

      1. solo server mode:该模式中webServer和executorServer运行在同一个进程中,进程名是AzkabanSingleServer。使用自带的H2数据库。这种模式包含Azkaban的所有特性,但一般用来学习和测试。
      2. two-server mode: 该模式使用MySQL数据库, Web Server和Executor Server运行在不同的进程中。
      3. multiple-executor mode该模式使用MySQL数据库, Web Server和Executor Server运行在不同的机器中。且有多个Executor Server。该模式适用于大规模应用。

          Azkaban源码编译

          Azkaban3.x在安装前需要自己编译成二进制包。并且提前安装好Maven、Ant、Node等软件。

          编译环境

          yum install –y git

          yum install –y gcc-c++

         下载源码并解压

          wget https://github.com/azkaban/azkaban/archive/3.51.0.tar.gz

          tar -zxvf 3.51.0.tar.gz

          cd ./azkaban-3.51.0/

          编译源码

          ./gradlew build installDist -x test

          编译成功之后就可以在指定的路径下取得对应的安装包了。

          #solo-server模式安装包路径

          azkaban-solo-server/build/distributions/

          #two-server模式和multiple-executor模式web-server安装包路径

          azkaban-web-server/build/distributions/

          #two-server模式和multiple-executor模式exec-server安装包路径

          azkaban-exec-server/build/distributions/

          #数据库相关安装包路径

          azkaban-db/build/distributions/

          Azkaban的安装,这里就不讲solo模式的和two server模式的了,步骤都是一样的,只是安装的机器不同而已。

             节点规划

              

            安装包解压到指定目录

             mkdir /export/servers/azkaban

             tar -zxvf azkaban-web-server-0.1.0-SNAPSHOT.tar.gz –C /export/servers/azkaban/

             tar -zxvf azkaban-exec-server-0.1.0-SNAPSHOT.tar.gz –C /export/servers/azkaban/

              配置web-server服务器

            生成ssl证书:

              keytool -keystore keystore -alias jetty -genkey -keyalg RSA

              运行此命令后,会提示输入当前生成keystore的密码及相应信息,输入的密码请记住。

              完成上述工作后,将在当前目录生成keystore证书文件,将keystore拷贝到 azkaban web服务器根目录中。

              如: cp keystore azkaban-web-server-0.1.0-SNAPSHOT/

            配置conf/azkaban.properties:   

    # Azkaban Personalization Settings
    azkaban.name=Test
    azkaban.label=My Local Azkaban
    azkaban.color=#FF3601
    azkaban.default.servlet.path=/index
    web.resource.dir=web/
    default.timezone.id=Asia/Shanghai # 时区注意后面不要有空格
    
    # Azkaban UserManager class
    user.manager.class=azkaban.user.XmlUserManager
    user.manager.xml.file=conf/azkaban-users.xml
    
    # Azkaban Jetty server properties. 开启使用ssl 并且知道端口
    jetty.use.ssl=true
    jetty.ssl.port=8443
    jetty.maxThreads=25
    
    # Azkaban Executor settings  指定本机Executor的运行端口
    executor.host=localhost
    executor.port=12321
    
    #  KeyStore for SSL ssl相关配置  注意密码和证书路径
    jetty.keystore=keystore
    jetty.password=123456
    jetty.keypassword=123456
    jetty.truststore=keystore
    jetty.trustpassword=123456
    
    # Azkaban mysql settings by default. Users should configure their own username and password.
    database.type=mysql
    mysql.port=3306
    mysql.host=node-1
    mysql.database=azkaban_two_server
    mysql.user=root
    mysql.password=hadoop
    mysql.numconnections=100
    
    #Multiple Executor 设置为false
    azkaban.use.multiple.executors=true
    #azkaban.executorselector.filters=StaticRemainingFlowSize,MinimumFreeMemory,CpuStatus 
    azkaban.executorselector.comparator.NumberOfAssignedFlowComparator=1
    azkaban.executorselector.comparator.Memory=1
    azkaban.executorselector.comparator.LastDispatched=1
    azkaban.executorselector.comparator.CpuUsage=1

            添加azkaban.native.lib=false 和 execute.as.user=false属性:

    1 mkdir -p plugins/jobtypes
    2 
    3 vim commonprivate.properties
    4 #键入下方代码
    5 azkaban.native.lib=false
    6 
    7 execute.as.user=false
    8 
    9 memCheck.enabled=false

           exec-server服务器配置

            配置conf/azkaban.properties:

     1 # Azkaban Personalization Settings
     2 azkaban.name=Test
     3 azkaban.label=My Local Azkaban
     4 azkaban.color=#FF3601
     5 azkaban.default.servlet.path=/index
     6 web.resource.dir=web/
     7 default.timezone.id=Asia/Shanghai
     8 
     9 # Azkaban UserManager class
    10 user.manager.class=azkaban.user.XmlUserManager
    11 user.manager.xml.file=conf/azkaban-users.xml
    12 
    13 # Loader for projects
    14 executor.global.properties=conf/global.properties
    15 azkaban.project.dir=projects
    16 
    17 # Where the Azkaban web server is located
    18 azkaban.webserver.url=https://node-2:8443
    19 
    20 # Azkaban mysql settings by default. Users should configure their own username and password.
    21 database.type=mysql
    22 mysql.port=3306
    23 mysql.host=node-1
    24 mysql.database=azkaban_two_server
    25 mysql.user=root
    26 mysql.password=hadoop
    27 mysql.numconnections=100
    28 
    29 # Azkaban Executor settings
    30 executor.maxThreads=50
    31 executor.port=12321
    32 executor.flow.threads=30

          集群启动

              先启动exec-server,再启动web-server。启动webServer之后进程失败消失,可通过安装包根目录下对应启动日志进行排查。

              

               需要手动激活executor

                cd  /export/servers/azkaban/execserver

                curl -G "node-2:$(<./executor.port)/executor?action=activate" && echo

              

                 然后重新启动webServer就可以了。

      Oozie:

          修改hadoop相关配置

            配置httpfs服务 

            修改hadoop的配置文件 core-site.xml

     1 <!--允许通过httpfs方式访问hdfs的主机名、域名;-->
     2 <property>
     3         <name>hadoop.proxyuser.root.hosts</name>
     4         <value>*</value>
     5 </property>
     6 <!--允许访问的客户端的用户组-->
     7 <property>
     8         <name>hadoop.proxyuser.root.groups</name>
     9         <value>*</value>
    10 </property>

             配置jobhistory服务

            修改hadoop的配置文件mapred-site.xml

     1 <property>
     2   <name>mapreduce.jobhistory.address</name>
     3   <value>node-1:10020</value>
     4   <description>MapReduce JobHistory Server IPC host:port</description>
     5 </property>
     6 
     7 <property>
     8   <name>mapreduce.jobhistory.webapp.address</name>
     9   <value>node-1:19888</value>
    10   <description>MapReduce JobHistory Server Web UI host:port</description>
    11 </property>
    12 <!-- 配置运行过的日志存放在hdfs上的存放路径 -->
    13 <property>
    14     <name>mapreduce.jobhistory.done-dir</name>
    15     <value>/export/data/history/done</value>
    16 </property>
    17 
    18 <!-- 配置正在运行中的日志在hdfs上的存放路径 -->
    19 <property>
    20     <name>mapreduce.jobhistory.intermediate-done-dir</name>
    21     <value>/export/data/history/done_intermediate</value>
    22 </property>

            重启history-server服务、重启Hadoop集群服务。

            上传oozie的安装包并解压

            oozie的安装包上传到/export/softwares

              tar -zxvf oozie-4.1.0-cdh5.14.0.tar.gz

            解压hadooplibs到与oozie平行的目录

              cd /export/servers/oozie-4.1.0-cdh5.14.0

              tar -zxvf oozie-hadooplibs-4.1.0-cdh5.14.0.tar.gz -C ../

            添加相关依赖

              oozie的安装路径下创建libext目录

                cd /export/servers/oozie-4.1.0-cdh5.14.0

                mkdir -p libext

              拷贝hadoop依赖包到libext

                cd /export/servers/oozie-4.1.0-cdh5.14.0

                cp -ra hadooplibs/hadooplib-2.6.0-cdh5.14.0.oozie-4.1.0-cdh5.14.0/* libext/

              上传mysql的驱动包到libext

                mysql-connector-java-5.1.32.jar

              添加ext-2.2.zip压缩包到libext

                ext-2.2.zip

              修改oozie-site.xml

              cd /export/servers/oozie-4.1.0-cdh5.14.0/conf

              vim oozie-site.xml

              oozie默认使用的是UTC的时区,需要在oozie-site.xml当中配置时区为GMT+0800时区

     1      <property>
     2         <name>oozie.service.JPAService.jdbc.driver</name>
     3         <value>com.mysql.jdbc.Driver</value>
     4     </property>
     5     <property>
     6         <name>oozie.service.JPAService.jdbc.url</name>
     7         <value>jdbc:mysql://node-1:3306/oozie</value>
     8     </property>
     9     <property>
    10         <name>oozie.service.JPAService.jdbc.username</name>
    11         <value>root</value>
    12     </property>
    13     <property>
    14         <name>oozie.service.JPAService.jdbc.password</name>
    15         <value>hadoop</value>
    16     </property>
    17     <property>
    18             <name>oozie.processing.timezone</name>
    19             <value>GMT+0800</value>
    20     </property>
    21 
    22     <property>
    23         <name>oozie.service.coord.check.maximum.frequency</name>
    24         <value>false</value>
    25     </property>     
    26 
    27     <property>
    28         <name>oozie.service.HadoopAccessorService.hadoop.configurations</name>
    29         <value>*=/export/servers/hadoop-2.7.5/etc/hadoop</value>
    30     </property>

               初始化mysql相关信息

              上传oozie的解压后目录的下的yarn.tar.gz到hdfs目录

                  bin/oozie-setup.sh  sharelib create -fs hdfs://node-1:9000 -locallib oozie-sharelib-4.1.0-cdh5.14.0-yarn.tar.gz

              本质上就是将这些jar包解压到了hdfs上面的路径下面去

              创建mysql数据库

                  mysql -uroot -p

                  create database oozie;

              初始化创建oozie的数据库表

                  cd /export/servers/oozie-4.1.0-cdh5.14.0

                  bin/oozie-setup.sh  db create -run -sqlfile oozie.sql

              打包项目,生成war包

                  cd /export/servers/oozie-4.1.0-cdh5.14.0

                  bin/oozie-setup.sh  prepare-war

             配置oozie环境变量     

    1 vim /etc/profile
    2 export OOZIE_HOME=/export/servers/oozie-4.1.0-cdh5.14.0
    3 export OOZIE_URL=http://node03.hadoop.com:11000/oozie
    4 export PATH=$PATH:$OOZIE_HOME/bin
    5 source /etc/profile

             启动关闭oozie服务

              启动命令

                cd /export/servers/oozie-4.1.0-cdh5.14.0

                bin/oozied.sh start

              关闭命令

                bin/oozied.sh stop

              如果意外关闭或者关机没关闭,那么重启之后再次启动会报错,需先删除上次启动时产生的pid文件,并且kill刚刚启动失败的进程,再次启动即可

                

              浏览器web UI页面

              http://node-1:11000/oozie/

    Azkaban与Oozie实战

        Azkaban使用实战

          shell command调度

            创建job描述文件

            vim command.job

    #command.job
    type=command                                                    
    command=echo 'hello'

          将job资源文件打包成zip文件

            zip command.job

          通过azkaban的web管理平台创建project并上传job压缩包

          首先创建Project

            

           上传zip包

            

           启动执行该job

            

             job依赖调度

             创建有依赖关系的多个job描述

                第一个job:foo.job

    1 # foo.job
    2 type=command
    3 command=echo foo

                第二个job:bar.job依赖foo.job

    1 # bar.job
    2 type=command
    3 dependencies=foo
    4 command=echo bar

               将所有job资源文件打到一个zip包中

               在azkaban的web管理界面创建工程并上传zip包

                启动工作流flow

         HDFS任务调度

    1 # fs.job
    2 type=command
    3 command=/home/hadoop/apps/hadoop-2.6.1/bin/hadoop fs -mkdir /azaz

            除了job文件内容不一样,其他步骤都是一致的

         MAPREDUCE任务调度

    1 # mrwc.job
    2 type=command
    3 command=/home/hadoop/apps/hadoop-2.6.1/bin/hadoop  jar hadoop-mapreduce-examples-2.6.1.jar wordcount /wordcount/input /wordcount/azout

          除了job文件内容不一样,其他步骤都是一致的

        HIVE脚本任务调度

    1 # hivef.job
    2 type=command
    3 command=/home/hadoop/apps/hive/bin/hive -f 'test.sql'

          除了job文件内容不一样,其他步骤都是一致的,这里既可以执行SQL文件也可以执行SQL语句,语法见hive篇

          定时任务调度

        

         上述图片中,选择左边schedule表示配置定时调度信息,选择右边execute表示立即执行工作流任务。

        

       Oozie使用实战:

          yarn容器资源分配属性

            yarn-site.xml  

     1 <!—节点最大可用内存,结合实际物理内存调整 -->
     2 <property>
     3         <name>yarn.nodemanager.resource.memory-mb</name>
     4         <value>3072</value>
     5 </property>
     6 <!—每个容器可以申请内存资源的最小值,最大值 -->
     7 <property>
     8         <name>yarn.scheduler.minimum-allocation-mb</name>
     9         <value>1024</value>
    10 </property>
    11 <property>
    12         <name>yarn.scheduler.maximum-allocation-mb</name>
    13         <value>3072</value>
    14 </property>
    15 
    16 <!—修改为Fair公平调度,动态调整资源,避免yarn上任务等待(多线程执行) -->
    17 <property>
    18  <name>yarn.resourcemanager.scheduler.class</name>
    19  <value>org.apache.hadoop.yarn.server.resourcemanager.scheduler.fair.FairScheduler</value>
    20 </property>
    21 <!—Fair调度时候是否开启抢占功能 -->
    22 <property>
    23         <name>yarn.scheduler.fair.preemption</name>
    24         <value>true</value>
    25 </property>
    26 <!—超过多少开始抢占,默认0.8-->
    27     <property>
    28         <name>yarn.scheduler.fair.preemption.cluster-utilization-threshold</name>
    29         <value>1.0</value>
    30 </property>

           mapreduce资源申请配置

            设置mapreduce.map.memory.mb和mapreduce.reduce.memory.mb配置

              否则Oozie读取的默认配置 -1, 提交给yarn的时候会抛异常Invalid resource request, requested memory < 0, or requested memory > max configured, requestedMemory=-1, maxMemory=8192

    mapred-site.xml

    1 <!—单个maptask、reducetask可申请内存大小 -->
    2 <property>
    3         <name>mapreduce.map.memory.mb</name>
    4         <value>1024</value>
    5 </property>
    6 <property>
    7         <name>mapreduce.reduce.memory.mb</name>
    8         <value>1024</value>
    9 </property>

          更新hadoop配置重启集群

              重启hadoop集群

               重启oozie服务

          Oozie调度shell脚本

             准备配置模板    

    #把shell的任务模板拷贝到oozie的工作目录当中去
    cd /export/servers/oozie-4.1.0-cdh5.14.0
    cp -r examples/apps/shell/ oozie_works/
    
    #准备待调度的shell脚本文件
    cd /export/servers/oozie-4.1.0-cdh5.14.0
    vim oozie_works/shell/hello.sh
    #注意:这个脚本一定要是在我们oozie工作路径下的shell路径下的位置
    #!/bin/bash
    echo "hello world" >> /export/servers/hello_oozie.txt

             修改配置模板

                修改job.properties

                cd /export/servers/oozie-4.1.0-cdh5.14.0/oozie_works/shell

                vim job.properties  

    1 nameNode=hdfs://node-1:8020 #HadoopNameNode地址
    2 jobTracker=node-1:8032    #Hadoop ResourceManager地址
    3 queueName=default        
    4 examplesRoot=oozie_works
    5 oozie.wf.application.path=${nameNode}/user/${user.name}/${examplesRoot}/shell #地址一定要跟你上传到HDFS上的路径保持一致
    6 EXEC=hello.sh

            jobTracker:在hadoop2当中,jobTracker这种角色已经没有了,只有resourceManager,这里给定resourceManager的IP及端口即可。

              queueName:提交mr任务的队列名;

              examplesRoot:指定oozie的工作目录;

              oozie.wf.application.path:指定oozie调度资源存储于hdfs的工作路径;

              EXEC:指定执行任务的名称。

          修改workflow.xml

     1 <workflow-app xmlns="uri:oozie:workflow:0.4" name="shell-wf">
     2 <start to="shell-node"/>
     3 <action name="shell-node">
     4     <shell xmlns="uri:oozie:shell-action:0.2">
     5         <job-tracker>${jobTracker}</job-tracker>
     6         <name-node>${nameNode}</name-node>
     7         <configuration>
     8             <property>
     9                 <name>mapred.job.queue.name</name>
    10                 <value>${queueName}</value>
    11             </property>
    12         </configuration>
    13         <exec>${EXEC}</exec>
    14         <file>/user/root/oozie_works/shell/${EXEC}#${EXEC}</file>
    15         <capture-output/>
    16     </shell>
    17     <ok to="end"/>
    18     <error to="fail"/>
    19 </action>
    20 <decision name="check-output">
    21     <switch>
    22         <case to="end">
    23             ${wf:actionData('shell-node')['my_output'] eq 'Hello Oozie'}
    24         </case>
    25         <default to="fail-output"/>
    26     </switch>
    27 </decision>
    28 <kill name="fail">
    29     <message>Shell action failed, error message[${wf:errorMessage(wf:lastErrorNode())}]</message>
    30 </kill>
    31 <kill name="fail-output">
    32     <message>Incorrect output, expected [Hello Oozie] but was [${wf:actionData('shell-node')['my_output']}]</message>
    33 </kill>
    34 <end name="end"/>
    35 </workflow-app>

          上传调度任务到hdfs

            注意:上传的hdfs目录为/user/root,因为hadoop启动的时候使用的是root用户,如果hadoop启动的是其他用户,那么就上传到/user/其他用户

            cd /export/servers/oozie-4.1.0-cdh5.14.0

            hdfs dfs -put oozie_works/ /user/root

           执行调度任务

            通过oozie的命令来执行调度任务

            cd /export/servers/oozie-4.1.0-cdh5.14.0

            bin/oozie job -oozie http://node-1:11000/oozie -config oozie_works/shell/job.properties  -run

         从监控界面可以看到任务执行成功了。

          

          可以通过jobhistory来确定调度时候是由那台机器执行的。

         Oozie调度Hive

        准备配置模板

          cd /export/servers/oozie-4.1.0-cdh5.14.0

          cp -ra examples/apps/hive2/ oozie_works/

         修改配置模板

          修改job.properties

            cd /export/servers/oozie-4.1.0-cdh5.14.0/oozie_works/hive2

            vim job.properties

    1 nameNode=hdfs://node-1:8020
    2 jobTracker=node-1:8032
    3 queueName=default
    4 jdbcURL=jdbc:hive2://node-1:10000/default
    5 examplesRoot=oozie_works
    6 
    7 oozie.use.system.libpath=true
    8 # 配置我们文件上传到hdfs的保存路径 实际上就是在hdfs 的/user/root/oozie_works/hive2这个路径下
    9 oozie.wf.application.path=${nameNode}/user/${user.name}/${examplesRoot}/hive2

        workflow.xml无变化,之后的步骤都是一样的,执行之后可以在监控页面进行查看,但是执行之前确保hiveserver2的服务一定要启动。

       Oozie调度MapReduce    

           准备配置模板

              准备mr程序的待处理数据。用hadoop自带的MR程序来运行wordcount。

              准备数据上传到HDFS的/oozie/input路径下去

              hdfs dfs -mkdir -p /oozie/input

              hdfs dfs -put wordcount.txt /oozie/input

     

           拷贝MR的任务模板

              cd /export/servers/oozie-4.1.0-cdh5.14.0

              cp -ra examples/apps/map-reduce/ oozie_works/

            删掉MR任务模板lib目录下自带的jar包

              cd /export/servers/oozie-4.1.0-cdh5.14.0/oozie_works/map-reduce/lib

              rm -rf oozie-examples-4.1.0-cdh5.14.0.jar

     

          拷贝官方自带mr程序jar包到对应目录

              cp /export/servers/hadoop-2.7.5/share/hadoop/mapreduce/hadoop-mapreduce-examples-2.7.5.jar /export/servers/oozie-4.1.0-cdh5.14.0/oozie_works/map-reduce/lib/


          修改配置模板

              修改job.properties

              cd /export/servers/oozie-4.1.0-cdh5.14.0/oozie_works/map-reduce

              vim job.properties

    1 nameNode=hdfs://node-1:8020
    2 jobTracker=node-1:8032
    3 queueName=default
    4 examplesRoot=oozie_works
    5 
    6 oozie.wf.application.path=${nameNode}/user/${user.name}/${examplesRoot}/map-reduce/workflow.xml
    7 outputDir=/oozie/output
    8 inputdir=/oozie/input

              修改workflow.xml

              cd /export/servers/oozie-4.1.0-cdh5.14.0/oozie_works/map-reduce

              vim workflow.xml

     1 <?xml version="1.0" encoding="UTF-8"?>
     2 <workflow-app xmlns="uri:oozie:workflow:0.5" name="map-reduce-wf">
     3     <start to="mr-node"/>
     4     <action name="mr-node">
     5         <map-reduce>
     6             <job-tracker>${jobTracker}</job-tracker>
     7             <name-node>${nameNode}</name-node>
     8             <prepare>
     9                 <delete path="${nameNode}/${outputDir}"/>
    10             </prepare>
    11             <configuration>
    12                 <property>
    13                     <name>mapred.job.queue.name</name>
    14                     <value>${queueName}</value>
    15                 </property>
    16         <!-- 开启使用新的API来进行配置 -->
    17                 <property>
    18                     <name>mapred.mapper.new-api</name>
    19                     <value>true</value>
    20                 </property>
    21 
    22                 <property>
    23                     <name>mapred.reducer.new-api</name>
    24                     <value>true</value>
    25                 </property>
    26 
    27                 <!-- 指定MR的输出key的类型 -->
    28                 <property>
    29                     <name>mapreduce.job.output.key.class</name>
    30                     <value>org.apache.hadoop.io.Text</value>
    31                 </property>
    32 
    33                 <!-- 指定MR的输出的value的类型-->
    34                 <property>
    35                     <name>mapreduce.job.output.value.class</name>
    36                     <value>org.apache.hadoop.io.IntWritable</value>
    37                 </property>
    38 
    39                 <!-- 指定输入路径 -->
    40                 <property>
    41                     <name>mapred.input.dir</name>
    42                     <value>${nameNode}/${inputdir}</value>
    43                 </property>
    44 
    45                 <!-- 指定输出路径 -->
    46                 <property>
    47                     <name>mapred.output.dir</name>
    48                     <value>${nameNode}/${outputDir}</value>
    49                 </property>
    50 
    51                 <!-- 指定执行的map类 -->
    52                 <property>
    53                     <name>mapreduce.job.map.class</name>
    54                     <value>org.apache.hadoop.examples.WordCount$TokenizerMapper</value>
    55                 </property>
    56 
    57                 <!-- 指定执行的reduce类 -->
    58                 <property>
    59                     <name>mapreduce.job.reduce.class</name>
    60                     <value>org.apache.hadoop.examples.WordCount$IntSumReducer</value>
    61                 </property>
    62                 <!--  配置map task的个数 -->
    63                 <property>
    64                     <name>mapred.map.tasks</name>
    65                     <value>1</value>
    66                 </property>
    67 
    68             </configuration>
    69         </map-reduce>
    70         <ok to="end"/>
    71         <error to="fail"/>
    72     </action>
    73     <kill name="fail">
    74         <message>Map/Reduce failed, error message[${wf:errorMessage(wf:lastErrorNode())}]</message>
    75     </kill>
    76     <end name="end"/>
    77 </workflow-app>
    View Code

            这一步最为复杂与繁琐,一定要细心,要彻底理解MR 程序的运行步骤,设置好每个步骤的Key和value的类型与对应类的类名。

            后续步骤没有什么变化,运行MR程序调度最重要也是最容易出错就是workflow.xml配置的错误。报错仔细检查

      Oozie任务串联

          在实际工作当中,肯定会存在多个任务需要执行,并且存在上一个任务的输出结果作为下一个任务的输入数据这样的情况,所以我们需要在workflow.xml配置文件当中配置多个action,实现多个任务之间的相互依赖关系。

          需求:首先执行一个shell脚本,执行完了之后再执行一个MR的程序,最后再执行一个hive的程序。

          准备工作目录

            cd /export/servers/oozie-4.1.0-cdh5.14.0/oozie_works

            mkdir -p sereval-actions

           准备调度文件

            将之前的hive,shell, MR的执行,进行串联成到一个workflow当中。

            cd /export/servers/oozie-4.1.0-cdh5.14.0/oozie_works

            cp hive2/script.q sereval-actions/

            cp shell/hello.sh sereval-actions/

            cp -ra map-reduce/lib sereval-actions/

         修改配置模板

            cd /export/servers/oozie-4.1.0-cdh5.14.0/oozie_works/sereval-actions

            vim workflow.xml

      1 <workflow-app xmlns="uri:oozie:workflow:0.4" name="shell-wf">
      2 <start to="shell-node"/>
      3 <action name="shell-node">
      4     <shell xmlns="uri:oozie:shell-action:0.2">
      5         <job-tracker>${jobTracker}</job-tracker>
      6         <name-node>${nameNode}</name-node>
      7         <configuration>
      8             <property>
      9                 <name>mapred.job.queue.name</name>
     10                 <value>${queueName}</value>
     11             </property>
     12         </configuration>
     13         <exec>${EXEC}</exec>
     14         <!-- <argument>my_output=Hello Oozie</argument> -->
     15         <file>/user/root/oozie_works/sereval-actions/${EXEC}#${EXEC}</file>
     16 
     17         <capture-output/>
     18     </shell>
     19     <ok to="mr-node"/>
     20     <error to="mr-node"/>
     21 </action>
     22 
     23 <action name="mr-node">
     24         <map-reduce>
     25             <job-tracker>${jobTracker}</job-tracker>
     26             <name-node>${nameNode}</name-node>
     27             <prepare>
     28                 <delete path="${nameNode}/${outputDir}"/>
     29             </prepare>
     30             <configuration>
     31                 <property>
     32                     <name>mapred.job.queue.name</name>
     33                     <value>${queueName}</value>
     34                 </property>
     35                 <!--  
     36                 <property>
     37                     <name>mapred.mapper.class</name>
     38                     <value>org.apache.oozie.example.SampleMapper</value>
     39                 </property>
     40                 <property>
     41                     <name>mapred.reducer.class</name>
     42                     <value>org.apache.oozie.example.SampleReducer</value>
     43                 </property>
     44                 <property>
     45                     <name>mapred.map.tasks</name>
     46                     <value>1</value>
     47                 </property>
     48                 <property>
     49                     <name>mapred.input.dir</name>
     50                     <value>/user/${wf:user()}/${examplesRoot}/input-data/text</value>
     51                 </property>
     52                 <property>
     53                     <name>mapred.output.dir</name>
     54                     <value>/user/${wf:user()}/${examplesRoot}/output-data/${outputDir}</value>
     55                 </property>
     56                 -->
     57                 
     58                    <!-- 开启使用新的API来进行配置 -->
     59                 <property>
     60                     <name>mapred.mapper.new-api</name>
     61                     <value>true</value>
     62                 </property>
     63 
     64                 <property>
     65                     <name>mapred.reducer.new-api</name>
     66                     <value>true</value>
     67                 </property>
     68 
     69                 <!-- 指定MR的输出key的类型 -->
     70                 <property>
     71                     <name>mapreduce.job.output.key.class</name>
     72                     <value>org.apache.hadoop.io.Text</value>
     73                 </property>
     74 
     75                 <!-- 指定MR的输出的value的类型-->
     76                 <property>
     77                     <name>mapreduce.job.output.value.class</name>
     78                     <value>org.apache.hadoop.io.IntWritable</value>
     79                 </property>
     80 
     81                 <!-- 指定输入路径 -->
     82                 <property>
     83                     <name>mapred.input.dir</name>
     84                     <value>${nameNode}/${inputdir}</value>
     85                 </property>
     86 
     87                 <!-- 指定输出路径 -->
     88                 <property>
     89                     <name>mapred.output.dir</name>
     90                     <value>${nameNode}/${outputDir}</value>
     91                 </property>
     92 
     93                 <!-- 指定执行的map类 -->
     94                 <property>
     95                     <name>mapreduce.job.map.class</name>
     96                     <value>org.apache.hadoop.examples.WordCount$TokenizerMapper</value>
     97                 </property>
     98 
     99                 <!-- 指定执行的reduce类 -->
    100                 <property>
    101                     <name>mapreduce.job.reduce.class</name>
    102                     <value>org.apache.hadoop.examples.WordCount$IntSumReducer</value>
    103                 </property>
    104                 <!--  配置map task的个数 -->
    105                 <property>
    106                     <name>mapred.map.tasks</name>
    107                     <value>1</value>
    108                 </property>
    109 
    110             </configuration>
    111         </map-reduce>
    112         <ok to="hive2-node"/>
    113         <error to="fail"/>
    114     </action>
    115 
    116 
    117 
    118 
    119 
    120 
    121  <action name="hive2-node">
    122         <hive2 xmlns="uri:oozie:hive2-action:0.1">
    123             <job-tracker>${jobTracker}</job-tracker>
    124             <name-node>${nameNode}</name-node>
    125             <prepare>
    126                 <delete path="${nameNode}/user/${wf:user()}/${examplesRoot}/output-data/hive2"/>
    127                 <mkdir path="${nameNode}/user/${wf:user()}/${examplesRoot}/output-data"/>
    128             </prepare>
    129             <configuration>
    130                 <property>
    131                     <name>mapred.job.queue.name</name>
    132                     <value>${queueName}</value>
    133                 </property>
    134             </configuration>
    135             <jdbc-url>${jdbcURL}</jdbc-url>
    136             <script>script.q</script>
    137             <param>INPUT=/user/${wf:user()}/${examplesRoot}/input-data/table</param>
    138             <param>OUTPUT=/user/${wf:user()}/${examplesRoot}/output-data/hive2</param>
    139         </hive2>
    140         <ok to="end"/>
    141         <error to="fail"/>
    142     </action>
    143 <decision name="check-output">
    144     <switch>
    145         <case to="end">
    146             ${wf:actionData('shell-node')['my_output'] eq 'Hello Oozie'}
    147         </case>
    148         <default to="fail-output"/>
    149     </switch>
    150 </decision>
    151 <kill name="fail">
    152     <message>Shell action failed, error message[${wf:errorMessage(wf:lastErrorNode())}]</message>
    153 </kill>
    154 <kill name="fail-output">
    155     <message>Incorrect output, expected [Hello Oozie] but was [${wf:actionData('shell-node')['my_output']}]</message>
    156 </kill>
    157 <end name="end"/>
    158 </workflow-app>
    View Code

            其实仔细观察就会发现,这里面的逻辑就是开始节点指定要执行的任务,然后执行完的动作中指定另一个任务,以此类推。

         job.properties配置文件

    nameNode=hdfs://node-1:8020
    jobTracker=node-1:8032
    queueName=default
    examplesRoot=oozie_works
    EXEC=hello.sh
    outputDir=/oozie/output
    inputdir=/oozie/input
    jdbcURL=jdbc:hive2://node-1:10000/default
    oozie.use.system.libpath=true
    # 配置我们文件上传到hdfs的保存路径 实际上就是在hdfs 的/user/root/oozie_works/sereval-actions这个路径下
    oozie.wf.application.path=${nameNode}/user/${user.name}/${examplesRoot}/sereval-actions/workflow.xml

        剩余的步骤都是一样的。执行完到监控系统上查看执行情况。

     Oozie定时调度

      在oozie当中,主要是通过Coordinator 来实现任务的定时调度, Coordinator 模块主要通过xml来进行配置即可。

      Coordinator 的调度主要可以有两种实现方式

      第一种:基于时间的定时任务调度:

      oozie基于时间的调度主要需要指定三个参数,第一个起始时间,第二个结束时间,第三个调度频率;

      第二种:基于数据的任务调度, 这种是基于数据的调度,只要在有了数据才会触发调度任务。

         准备配置模板

      第一步:拷贝定时任务的调度模板

      cd /export/servers/oozie-4.1.0-cdh5.14.0

      cp -r examples/apps/cron oozie_works/cron-job

       第二步:拷贝我们的hello.sh脚本

      cd /export/servers/oozie-4.1.0-cdh5.14.0/oozie_works

      cp shell/hello.sh  cron-job/

         修改配置模板

           修改job.properties

            cd /export/servers/oozie-4.1.0-cdh5.14.0/oozie_works/cron-job

            vim job.properties

     1 nameNode=hdfs://node-1:8020
     2 jobTracker=node-1:8032
     3 queueName=default
     4 examplesRoot=oozie_works
     5 
     6 oozie.coord.application.path=${nameNode}/user/${user.name}/${examplesRoot}/cron-job/coordinator.xml
     7 #start:必须设置为未来时间,否则任务失败
     8 start=2019-05-22T19:20+0800
     9 end=2019-08-22T19:20+0800
    10 EXEC=hello.sh
    11 workflowAppUri=${nameNode}/user/${user.name}/${examplesRoot}/cron-job/workflow.xml

           修改coordinator.xml

            vim coordinator.xml

     1 <!--
     2     oozie的frequency 可以支持很多表达式,其中可以通过定时每分,或者每小时,或者每天,或者每月进行执行,也支持可以通过与linux的crontab表达式类似的写法来进行定时任务的执行
     3     例如frequency 也可以写成以下方式
     4     frequency="10 9 * * *"  每天上午的09:10:00开始执行任务
     5     frequency="0 1 * * *"  每天凌晨的01:00开始执行任务
     6  -->
     7 <coordinator-app name="cron-job" frequency="${coord:minutes(1)}" start="${start}" end="${end}" timezone="GMT+0800"
     8                  xmlns="uri:oozie:coordinator:0.4">
     9         <action>
    10         <workflow>
    11             <app-path>${workflowAppUri}</app-path>
    12             <configuration>
    13                 <property>
    14                     <name>jobTracker</name>
    15                     <value>${jobTracker}</value>
    16                 </property>
    17                 <property>
    18                     <name>nameNode</name>
    19                     <value>${nameNode}</value>
    20                 </property>
    21                 <property>
    22                     <name>queueName</name>
    23                     <value>${queueName}</value>
    24                 </property>
    25             </configuration>
    26         </workflow>
    27     </action>
    28 </coordinator-app>

             workflow.xml跟之前的一样,剩余步骤相同,上传到HDFS上执行,在监控系统查看

    两个工作流调度的系统,就大致这些内容了,更深层次的使用,可以参考官网文档。

  • 相关阅读:
    easyUI 后台经典框架DEMO下载
    一个通过JSONP跨域调用WCF REST服务的例子(以jQuery为例)
    WCF的三个名称/命名空间,你是否傻傻分不清楚?
    未找到与约束ContractName Microsoft.VisualStudio.Text.ITextDocumentFactoryService... 匹配的导出 VS2012报错
    jquery easyui tabs单击刷新右键刷新
    在64位Windows7上安装64位Oracle11g
    Linux入门
    服务器硬件知识
    IP后面带/30 /29 /27等是什么意思?
    vitualbox安装centos7卡死
  • 原文地址:https://www.cnblogs.com/sky9408251/p/12069277.html
Copyright © 2011-2022 走看看