大数据Hadoop之——任务调度器Oozie(Oozie环境部署)

Posted 大数据老司机

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了大数据Hadoop之——任务调度器Oozie(Oozie环境部署)相关的知识,希望对你有一定的参考价值。

@[TOC]

一、概述

Oozie的特点:

  • Oozie是管理hadoop作业的调度系统;
  • Oozie的工作流作业是一系列动作的有向无环图(DAG)
  • Oozie协调作业是通过时间(频率)和有效数据触发当前的Oozie工作流程;
  • 工作流通过hPDL定义(一种XML流程定义语言);
  • 资源文件(脚本、jar包等)存放在HDFS
  • Oozie支持各种hadoop作业,例如:java map-reduce、Streaming map-reduce、pig、hive、sqoop和distcp等等,也支持系统特定的作业,例如java程序和shell脚本;
  • Oozie是一个可伸缩,可靠和可拓展的系统。

二、Oozie架构


Oozie三层结构:

  • Workflow:工作流,由我们需要处理的每个工作组成,进行需求的流式处理,是对要进行的顺序化工作的抽象。
    1. 控制节点(CONTROL NODE):控制流节点一般都是定义在工作流开始或者结束的位置,比如start,end,kill等。以及提供工作流的执行路径机制,如decision, fork, join等。
    2. 动作节点(ACTION NODE) : 负责执行具体动作的节点,比如:拷贝文件,执行某个hive、shell、sqoop、pig、mr等等。

流程图如下:

  • Coordinator:协调器,可以理解为工作流的协调器,可以将多个工作流协调成一个工作流来进行处理,是对要进行的顺序化的workflow的抽象,定时触发一个workflow。流程图如下:

  • Bundle:捆,束。将一堆的coordinator进行汇总处理,是对一堆coordiantor的抽象,用来绑定多个coordinator或者多个workflow,流程图如下:

三、Oozie环境部署(Oozie与CDH集成)

1)添加服务


2)将 Oozie 服务添加到 CDH

3)自定义角色分配

4)数据库设置


5)审核更改

默认就行,当然可以自行修改

6)开始自动安装并自启


到这里Oozie服务就安装完成了。

四、CDH的 Hue 整合 Oozie

由于oozie的xml配置执行各种任务调度是在太过于繁琐,所有一般都使用hue整合oozie来使用。

修改配置

重启Hue服务

重新登录Hue web

发现多了计划程序,这就是Oozie的计划程序

五、Oozie简单使用

1)在Hue上操作Oozie

1、利用 Hue 调度 shell 脚本

1、创建workflow

2、查看workflow

3、配置调用任务




保存

4、立即执行

发现报错了

原因是 yarn配置的最大容器申请资源是1024M,oozie配置的启动资源要2048M,在CM中修改oozie的相关配置。

重启服务后重新执行

再去看Yarn任务

其实这里只是加了一个任务,其实可以加很多任务,接下来就可自行扩展了

2、利用 Hue 调度 hive 脚本

sql文件

create database test001;
CREATE TABLE  IF NOT EXISTS test001.person_1 (
id INT COMMENT ID,
name STRING COMMENT 名字,
age INT COMMENT 年龄,
likes ARRAY<STRING> COMMENT 爱好,
address MAP<STRING,STRING> COMMENT 地址
)
ROW FORMAT DELIMITED
FIELDS TERMINATED BY ,
COLLECTION ITEMS TERMINATED BY -
MAP KEYS TERMINATED BY :
LINES TERMINATED BY \\n;

跟前面的步骤一样,只是调度的任务不同和脚本不同而已,这里就不再过多截图介绍了。

通过beeline连接hive检查

$ beeline -u jdbc:hive2://hadoop-cdhmaster-168-182-161:10000  -n root
show databases;
show tables from test001;

当然也对应有个yarn任务

3、 利用 Hue 配置定时调度任务

选择workflow

提交Schedule


2)CLI操作Oozie

一个Oozie 的 job 一般由以下文件组成:

  • job.properties :记录了job的属性
  • workflow.xml:使用hPDL 定义任务的流程和分支
  • 脚本文件/lib目录:用来执行具体的任务的文件

    job.properties
    key 含义
    nameNode HDFS地址
    jobTracker jobTracker(ResourceManager)地址
    queueName Oozie队列(默认填写default)
    examplesRoot 全局目录(默认填写examples)
    oozie.usr.system.libpath 是否加载用户lib目录(true/false)
    oozie.libpath 用户lib库所在的位置
    oozie.wf.application.path Oozie流程所在hdfs地址(workflow.xml所在的地址)
    user.name 当前用户
    oozie.coord.application.path Coordinator.xml地址(没有可以不写)
    oozie.bundle.application.path Bundle.xml地址(没有可以不写)

1、CLI 调度 shell 脚本

$ tar -xf oozie-examples.tar.gz
$ cd examples/apps/
$ ll

很多示例,这里只演示几个,其余的小伙伴可以自行练习一下

进入到shell的示例目录,发现有两个配置文件job.propertiesworkflow.xml

$ cd shell

修改job.properties

# 配置hdfs,地址记得改成自己环境的
nameNode=hdfs://hadoop-cdhslave01-168-182-162:8020
# 配置yarn,8088是web端口,8032是yarn的服务端口号
resourceManager=hadoop-cdhslave01-168-182-162:8032
queueName=default
examplesRoot=examples

# HDFS脚本文件存放目录
oozie.wf.application.path=$nameNode/user/$user.name/workflow/shell

# 定义脚本变量,也可以直接写脚本名字
shellScript=helloworld.sh

修改workflow.xml

脚本:helloworld.sh
```bash
#!/bin/bash
echo `date` " hello world" >> /tmp/helloworld.log

可以在job.properties定义一个变量,在workflow.xml中使用变量
把三个文件都上传到/user/oozie/workflow/shell/目录下

$ sudo -u oozie hadoop fs -mkdir -p /user/oozie/workflow/shell/
$ sudo -u oozie hadoop fs -put * /user/oozie/workflow/shell/

立即执行任务

$ sudo -u oozie /usr/bin/oozie job -oozie http://hadoop-cdhslave02-168-182-163:11000/oozie/ -config job.properties -run

Oozie web UI查看,登录web时,发现有问题

【Oozie web console is disabled 问题解决】

$ find /opt/ -name libext
$ cd /opt/cloudera/parcels/CDH-6.3.2-1.cdh6.3.2.p0.1605554/lib/oozie/libext
$ wget http://archive.cloudera.com/gplextras/misc/ext-2.2.zip
$ sudo unzip ext-2.2.zip
$ sudo chown oozie:oozie -R ext-2.2

执行成功了

再去看一下yarn任务

2、执行多个任务job

$ cd /opt/cloudera/parcels/CDH-6.3.2-1.cdh6.3.2.p0.1605554/share/doc/oozie-5.1.0+cdh6.3.2/examples/apps
# copy一份shell文件
$ cp -r shell shell02
$ cd shell02

新建一个shell脚本,test02.sh

#!/bin/bash
echo "test mutil workflow" >> /tmp/test02.log

修改job.properties

# 配置hdfs,地址记得改成自己环境的
nameNode=hdfs://hadoop-cdhslave01-168-182-162:8020
# 配置yarn,8088是web端口,8032是yarn的服务端口号
resourceManager=hadoop-cdhslave01-168-182-162:8032
queueName=default
examplesRoot=examples

# HDFS脚本文件存放目录
oozie.wf.application.path=$nameNode/user/$user.name/workflow/shell

# 定义脚本变量,也可以直接写脚本名字
shellScript=helloworld.sh
# 新增一个脚本变量
shellScript02=test02.sh

修改workflow.xml,新增一个action

<workflow-app xmlns="uri:oozie:workflow:1.0" name="shell-wf">
    <start to="shell-node01"/>
    <action name="shell-node01">
        <shell xmlns="uri:oozie:shell-action:1.0">
            <resource-manager>$resourceManager</resource-manager>
            <name-node>$nameNode</name-node>
            <configuration>
                <property>
                    <name>mapred.job.queue.name</name>
                    <value>$queueName</value>
                </property>
            </configuration>
            <exec>$shellScript</exec>
            <file>/user/oozie/workflow/shell/$shellScript#$shellScript</file>
            <capture-output/>
        </shell>
        <ok to="shell-node02"/>
        <error to="fail"/>
    </action>
    <action name="shell-node02">
        <shell xmlns="uri:oozie:shell-action:1.0">
            <resource-manager>$resourceManager</resource-manager>
            <name-node>$nameNode</name-node>
            <configuration>
                <property>
                    <name>mapred.job.queue.name</name>
                    <value>$queueName</value>
                </property>
            </configuration>
            <exec>$shellScript02</exec>
            <file>/user/oozie/workflow/shell/$shellScript02#$shellScript02</file>
            <capture-output/>
        </shell>
        <ok to="end"/>
        <error to="fail"/>
    </action>

    <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>

强制覆盖

$ sudo -u oozie hadoop fs -put -f * /user/oozie/workflow/shell/

执行任务

$ sudo -u oozie /usr/bin/oozie job -oozie http://hadoop-cdhslave02-168-182-163:11000/oozie/ -config job.properties -run


3、调度MR任务

直接使用官方模板修改(wordcount示例)

$ cd /opt/cloudera/parcels/CDH-6.3.2-1.cdh6.3.2.p0.1605554/share/doc/oozie-5.1.0+cdh6.3.2/examples/apps/map-reduce
$ ll
$ tree lib/

先用传统方式验证一把

$ cat>./wordcount.txt<< EOF
hello oozie
hello hadoop
hadoo oozie
hello world
hello bigdata
bigdata hadoop
hello flink
EOF
$ sudo -u hdfs hadoop fs -put wordcount.txt /
# 找到hadoop-mapreduce-examples*.jar包
$ find /opt/ -name hadoop-mapreduce-examples*.jar
$ sudo -u hdfs yarn jar /opt/cloudera/parcels/CDH-6.3.2-1.cdh6.3.2.p0.1605554/jars/hadoop-mapreduce-examples-3.0.0-cdh6.3.2.jar wordcount /wordcount.txt /out

配置workflow.xml

先在上面的跑的任务中查找map类和reduce

map类

reduce类

修改后的workflow.xml内容如下:

<workflow-app xmlns="uri:oozie:workflow:1.0" name="map-reduce-wf">
    <start to="mr-node"/>
    <action name="mr-node">
        <map-reduce>
            <resource-manager>$resourceManager</resource-manager>
            <name-node>$nameNode</name-node>
            <prepare>
                <delete path="$nameNode/user/oozie/workflow/map-reduce/output/"/>
            </prepare>
            <configuration>
                <property>
                    <name>mapred.job.queue.name</name>
                    <value>$queueName</value>
                </property>
                <!-- 配置MR调度任务时,设置使用新的API-->
                <property>
                    <name>mapred.mapper.new-api</name>
                    <value>true</value>
                </property>
                <property>
                    <name>mapred.reducer.new-api</name>
                    <value>true</value>
                </property>
                <!-- 指定job key输出类型 -->
                <property>
                    <name>mapreduce.job.output.key.class</name>
                    <value>org.apache.hadoop.io.Text</value>
                </property>
                <!-- 指定job value输出类型 -->
                <property>
                    <name>mapreduce.job.output.value.class</name>
                    <value>org.apache.hadoop.io.IntWritable</value>
                </property>
                <!-- 指定输入路径 -->
                <property>
                    <name>mapred.input.dir</name>
                    <value>/user/oozie/workflow/map-reduce/wordcount.txt</value>
                </property>
                <!-- 指定输出路径 -->
                <property>
                    <name>mapred.output.dir</name>
                    <value>/user/oozie/workflow/map-reduce/output/</value>
                </property>
                <!-- 指定map类 -->
                <property>
                    <name>mapreduce.job.map.class</name>
                    <value>org.apache.hadoop.examples.WordCount$TokenizerMapper</value>
                </property>
                <!-- 指定reduce类 -->
                <property>
                    <name>mapreduce.job.reduce.class</name>
                    <value>org.apache.hadoop.examples.WordCount$IntSumReducer</value>
                </property>
                <property>
                    <name>mapred.map.tasks</name>
                    <value>1</value>
                </property>
            </configuration>
        </map-reduce>
        <ok to="end"/>
        <error to="fail"/>
    </action>
    <kill name="fail">
        <message>Map/Reduce failed, error message[$wf:errorMessage(wf:lastErrorNode())]</message>
    </kill>
    <end name="end"/>
</workflow-app>

修改job.properties,内容如下:

# 配置hdfs,地址记得改成自己环境的
nameNode=hdfs://hadoop-cdhslave01-168-182-162:8020
# 配置yarn,8088是web端口,8032是yarn的服务端口号
resourceManager=hadoop-cdhslave01-168-182-162:8032
queueName=default
examplesRoot=examples

oozie.wf.application.path=$nameNode/user/$user.name/workflow/map-reduce/workflow.xml

# 定义脚本变量,也可以直接写脚本名字
outputDir=map-reduce

换掉lib下面的jar包,使用新API

$ cd /opt/cloudera/parcels/CDH-6.3.2-1.cdh6.3.2.p0.1605554/share/doc/oozie-5.1.0+cdh6.3.2/examples/apps
$ cp /opt/cloudera/parcels/CDH-6.3.2-1.cdh6.3.2.p0.1605554/jars/hadoop-mapreduce-examples-3.0.0-cdh6.3.2.jar map-reduce/lib/
$ rm -f map-reduce/lib/oozie-examples-5.1.0-cdh6.3.2.jar

把map-reduce目录推到HDFS上

$ sudo -u oozie hadoop fs -put -f map-reduce /user/oozie/workflow/

执行任务

$ sudo -u oozie /usr/bin/oozie job -oozie http://hadoop-cdhslave02-168-182-163:11000/oozie/ -config map-reduce/job.properties -run

登录Oozie web UI:http://hadoop-cdhslave02-168-182-163:11000/oozie/

登录yarn web查看任务

4、调度定时任务

$ cd /opt/cloudera/parcels/CDH-6.3.2-1.cdh6.3.2.p0.1605554/share/doc/oozie-5.1.0+cdh6.3.2/examples/apps
$ cd cron

修改job.properties,内容如下:

nameNode=hdfs://hadoop-cdhslave01-168-182-162:8020
resourceManager=hadoop-cdhslave01-168-182-162:8032
queueName=default
examplesRoot=examples

oozie.coord.application.path=$nameNode/user/$user.name/workflow/cron
# start必须设置未来时间,否则任务会失败
start=2022-04-27T23:30Z
end=2022-04-29T01:00Z
workflowAppUri=$nameNode/user/$user.name/workflow/cron
shellScript=test001.sh

修改workflow.xml,其实也是上面第一个示例

<workflow-app xmlns="uri:oozie:workflow:1.0" name="shell-wf">
    <start to="shell-node"/>
    <action name="shell-node">
        <shell xmlns="uri:oozie:shell-action:1.0">
            <resource-manager>$resourceManager</resource-manager>
            <name-node>$nameNode</name-node>
            <configuration>
                <property>
                    <name>mapred.job.queue.name</name>
                    <value>$queueName</value>
                </property>
            </configuration>
            <exec>$shellScript</exec>
            <file>/user/oozie/workflow/cron/$shellScript#$shellScript</file>
            <capture-output/>
        </shell>
        <ok to="end"/>
        <error to="fail"/>
    </action>
    <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>

修改coordinator.xml,内容如下:

$ cd ..
$ sudo -u oozie hadoop fs -put cron /user/oozie/workflow/

执行

$ sudo -u oozie /usr/bin/oozie job -oozie http://hadoop-cdhslave02-168-182-163:11000/oozie/ -config cron/job.properties -run

3)Java API操作Oozie

1、编辑好shell脚本和workflow.xml文件

$ mkdir -p /opt/test/oozie/workflow/shell
$ vi /opt/test/oozie/workflow/shell/ooziehello.sh
#!/bin/bash
name=$1
echo "hello $name" >> /tmp/oozieshell.log

$ vi /opt/test/oozie/workflow/shell/workflow.xml
<workflow-app xmlns="uri:oozie:workflow:1.0" name="shell-wf">
    <start to="shell-node"/>
    <action name="shell-node">
        <shell xmlns="uri:oozie:shell-action:1.0">
            <resource-manager>$resourceManager</resource-manager>
            <name-node>$nameNode</name-node>
            <configuration>
                <property>
                    <name>mapred.job.queue.name</name>
                    <value>$queueName</value>
                </property>
            </configuration>
            <exec>$shellScript</exec>
            <file>/user/oozie/workflow/oozieshell/$shellScript#$shellScript</file>
            <capture-output/>
        </shell>
        <ok to="end"/>
        <error to="fail"/>
    </action>
    <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>

3、把上面两个文件上传到HDFS

$ sudo -u oozie hadoop fs -mkdir /user/oozie/workflow/oozieshell/
$ sudo -u oozie hadoop fs -put * /user/oozie/workflow/oozieshell/

4、代码执行提交任务

package com.bigdata;

/**
 * workflow shell test
 */

import org.apache.oozie.client.OozieClient;
import org.apache.oozie.client.WorkflowAction;
import org.apache.oozie.client.WorkflowJob;
import java.util.List;
import java.util.Properties;

public class WorkFlowShellTest 
    public static void main(String[] args) 
        System.setProperty("user.name", "oozie");
        OozieClient oozieClient = new OozieClient("http://hadoop-cdhslave02-168-182-163:11000/oozie/");
        try 
            System.out.println(oozieClient.getServerBuildVersion());
            Properties properties = oozieClient.createConfiguration();
            properties.put("oozie.wf.application.path", "$nameNode/user/$user.name/workflow/oozieshell");
            properties.put("queueName", "default");
            properties.put("nameNode", "hdfs://hadoop-cdhslave01-168-182-162:8020");
            properties.put("resourceManager", "hadoop-cdhslave01-168-182-162:8032");
            properties.put("shellScript", "ooziehello.sh");
            properties.put("argument", "oozie");
            //运行workflow
            String jobid = oozieClient.run(properties);
            System.out.println("jobid:" + jobid);
            //根据workflow id获取作业运行情况
            WorkflowJob workflowJob = oozieClient.getJobInfo(jobid);
            //获取作业日志
            System.out.println(oozieClient.getJobLog(jobid));
            //获取workflow中所有ACTION
            List<WorkflowAction> list = workflowJob.getActions();
            for (WorkflowAction action : list) 
                //输出每个Action的 Appid 即Yarn的Application ID
                System.out.println(action.getExternalId());
            
         catch (Exception e) 
            e.printStackTrace();
        
    


其它的示例也类似,就是把之前的job.properties,用java格式加载,运行,查询,其它都一样。所以其它示例就由小伙伴自行练习了。

六、常用命令

# 启动
$ oozied.sh start
# 停止
$ oozied.sh stop
# 提交任务并启动任务(submit和start命令合并)
$ oozie job -oozie http://hadoop-cdhslave02-168-182-163:11000/oozie -config job.properties –run
# 提交任务不启动
$ oozie job -oozie http://hadoop-cdhslave02-168-182-163:11000/oozie -config job.properties –submit
# 启动任务
$ oozie job -oozie http://hadoop-cdhslave02-168-182-163:11000/oozie -start 0001837-220423150913947-oozie-oozi-W

### workflow任务
# 查看所有workflow任务
$ oozie jobs
# 查看信息
$ oozie job -oozie http://hadoop-cdhslave02-168-182-163:11000/oozie -info 0001837-220423150913947-oozie-oozi-W
# 查看日志
$ oozie job -oozie http://hadoop-cdhslave02-168-182-163:11000/oozie -log 0001837-220423150913947-oozie-oozi-W
# Kill任务
$ oozie job -oozie http://hadoop-cdhslave02-168-182-163:11000/oozie/ -kill 0001831-220423150913947-oozie-oozi-W
# 或者下面这句
$ oozie job -kill 0001831-220423150913947-oozie-oozi-W

### coordinator 定时任务
# 查看定时任务
$ oozie jobs -jobtype coordinator -oozie http://hadoop-cdhslave02-168-182-163:11000/oozie/
$ oozie jobs -jobtype coordinator
# 删除定时任务
$ oozie job -kill 0000345-220423150913947-oozie-oozi-C

七、Oozie与Azkaban对比

对比指标 Azkaban Oozie
功能 Azkaban与Oozie均可以调度mapreduce、pig、java脚本工作流任务;Azkaban与Oozie均可以定时执行工作流任务。 与Azkaban 一样
工作流传参 Azkaban支持直接传参,例如$input。 Oozie支持参数和EL表达式,例如$fs:dirSize(myInputDir)。
定时执行 Azkaban的定时执行任务是基于时间的。 Oozie的定时执行任务是基于时间和输入数据资源管理。
工作流执行 Azkaban有两种运行模式,分别是solo server mode(executor server和web server部署在同⼀台节点)和multi server mode(executor server和web server可以部署在不同节点)。 Oozie作为工作流服务运行,支持多用户和多工作流。

关于Azkaban,可以参考我之前的文章:
大数据Hadoop之——任务调度器Azkaban(Azkaban环境部署)
大数据Hadoop之——Azkaban API详解

关于Oozie的概述和简单使用就到这结束了,如果小伙伴有疑问,欢迎给我留言,未完待续,请耐心等待~

以上是关于大数据Hadoop之——任务调度器Oozie(Oozie环境部署)的主要内容,如果未能解决你的问题,请参考以下文章

必知Hadoop工作流引擎调度器--Azkaban与Oozie的区别。

云小课|MRS基础原理之Oozie任务调度

大数据用户画像之OozieHue集成Spark2 应用调度

调度工具(ETL+任务流)

一文带你了解大数据技术之Hadoop(Yarn)

Oozie