精华内容
下载资源
问答
  • Oozie定时调度框架完整篇 Oozie : 基于工作流引擎的开源框架,有Cloudera公司贡献给Apache,提供对Hadoop MapReduce Pig jobs 的任务调度与协调. 主要用于定时调度,多任务可以按照执行的逻辑顺序调度. 功能模块 模块...

    Oozie定时调度框架完整篇

    Oozie : 基于工作流引擎的开源框架,有Cloudera公司贡献给Apache,提供对Hadoop MapReduce Pig jobs 的任务调度与协调. 主要用于定时调度,多任务可以按照执行的逻辑顺序调度.

    功能模块

    模块组成 : 工作流,调度器,绑定任务

    WorkFlow : 顺序执行流程节点,支持fork(分支多个节点), join(合并多个节点为一个).

    Coordinator 定时触发工作流workflow.

    Bundle Job : 绑定多个调度器Coordinator.

    常用节点 :

    1. 控制流节点 (Control Flow Nodes)

      控制流节点一般是定义在工作流开始或者结束的位置(eg: start , end , kill …) , 以及提供工作流的执行机制 (eg : decision , fork , join…)

    2. 动作节点 (Action Nodes)

      负责执行具体的动作节点 , (eg:拷贝文件,执行某个Shell脚本等)

    Hadoop部署(CDH版本)

    修改Hadoop配置(注意主机名,路径,端口)

    core-site.xml

    <!-- 指定HDFS中NameNode的地址 -->
    <property>
            <name>fs.defaultFS</name>
            <value>hdfs://hadoop111:8020</value>
    </property>
    
    <!-- 指定Hadoop运行时产生文件的存储目录 -->
    <property>
            <name>hadoop.tmp.dir</name>
            <value>/opt/module/oozie/hadoop-2.5.0-cdh5.3.6/data/tmp</value>
    </property>
    
    <!-- Oozie Server的Hostname -->
    <property>
            <name>hadoop.proxyuser.dev.hosts</name>
            <value>*</value>
    </property>
    
    <!-- 允许被Oozie代理的用户组 -->
    <property>
            <name>hadoop.proxyuser.dev.groups</name>
            <value>*</value>
    </property>
    

    hdfs.xml

    <!--配置副本数-->
    <property>
            <name>dfs.replication</name>
            <value>3</value>
    </property>
    
    <!-- 指定Hadoop 辅助名称节点 SecondaryNameNode 主机配置 -->
    <property>
          <name>dfs.namenode.secondary.http-address</name>
          <value>hadoop113:50090</value>
    </property>
    

    mapred-site.xml

    <!-- 指定MR运行在YARN上 -->
    <property>
            <name>mapreduce.framework.name</name>
            <value>yarn</value>
    </property>
    
    <!-- 历史服务器端地址 -->
    <property>
            <name>mapreduce.jobhistory.address</name>
            <value>hadoop113:10020</value>
    </property>
    <!-- 历史服务器web端地址 -->
    <property>
        <name>mapreduce.jobhistory.webapp.address</name>
        <value>hadoop113:19888</value>
    </property>
    
    <!-- 任务历史服务器 -->
    <property>
    	<name>yarn.log.server.url</name> 
    	<value>http://hadoop113:19888/jobhistory/logs/</value> 
    </property>
    

    yarn-site.xml

    <!-- Reducer获取数据的方式 -->
    <property>
            <name>yarn.nodemanager.aux-services</name>
            <value>mapreduce_shuffle</value>
    </property>
    
    <!-- 指定YARN的ResourceManager的地址 -->
    <property>
            <name>yarn.resourcemanager.hostname</name>
            <value>hadoop112</value>
    </property>
    
    <!-- 日志聚集功能 -->
    <property>
            <name>yarn.log-aggregation-enable</name>
            <value>true</value>
    </property>
    
    <!--日志保留时间设置7天-->
    <property>
            <name>yarn.log-aggregation.retain-seconds</name>
            <value>604800</value>
    </property>
    

    分发到其他机器节点.

    xsync etc

    # 第一次启动格式化namenode
    bin/hdfs.sh namenode -format
    #启动集群
    sbin/start-dfs.sh
    sbin/start-yarn.sh (注意,尽量避免namenode同一台机器)
    # sbin/mr-jobhistory-daemon.sh start historyserver  (旧版本命令)
    sbin/mapred --daemon start historyserver
    

    Oozie部署(CDH版本)

    官网 : oozie.apache.org

    (1) 解压 oozie 压缩包

    tar -zxvf oozie-4.0.0-cdh5.3.6.tar.gz -C /opt/module/oozie/
    

    (2) 解压 oozie-hadooplibs 压缩包,直接解压到 oozie 根目录下 (或者移动 hadooplibs 到 oozie 根目录下

    tar -zxvf oozie-hadooplibs-4.0.0-cdh5.3.6.tar.gz ../
    

    (3) oozie根目录下创建文件夹 , 名称固定(读官网) : libext

    mkdir libext
    

    (4) 将hadooplibs里面 cdh目录下的jar包 , 拷贝到 libext 目录下

    cp hadooplibs/hadooplib-2.5.0-cdh5.3.6.oozie-4.0.0-cdh5.3.6/* libext/
    

    (5) 将ext-2.2.zip拷贝到 libext 目录下

    cp /opt/software/ext-2.2.zip libext
    

    (6) 数据库如果用mysql,需要将mysql连接驱动jar拷贝到 libext

    cp /opt/software/mysql-connector-java-5.1.47.jar libext
    

    (7) 修改Oozie配置文件 (注意修改mysql连接信息)

    vim conf/oozie-site.xml, 默认使用derby数据库

    <property>
        <name>oozie.service.JPAService.jdbc.driver</name>
        <value>com.mysql.jdbc.Driver</value>
        <description>JDBC驱动</description>
    </property>
    
    <property>
        <name>oozie.service.JPAService.jdbc.url</name>
        <value>jdbc:mysql://192.168.0.10:3306/oozie</value>
        <description>JDBC连接地址</description>
    </property>
    
    <property>
        <name>oozie.service.JPAService.jdbc.username</name>
        <value>root</value>
        <description>数据库用户</description>
    </property>
    
    <property>
        <name>oozie.service.JPAService.jdbc.password</name>
        <value>123</value>
        <description>数据库密码</description>
    </property>
    
    <property>
        <name>oozie.service.HadoopAccessorService.hadoop.configurations</name>
        <value>*=/opt/module/oozie/hadoop-2.5.0-cdh5.3.6/etc/hadoop</value>
        <description>配置hadoop配置文件路径,多个逗号分隔</description>
    </property>
    

    (8) 在Mysql中创建Oozie的数据库

    create database oozie;
    

    (9) 初始化Oozie

    提示 : yarn.tar.gz 文件上传到hdfs会自行解压 , 执行成功之后,看下上传目录是否存在

    bin/oozie-setup.sh sharelib create -fs hdfs://hadoop111:8020 -locallib oozie-sharelib-4.0.0-cdh5.3.6-yarn.tar.gz
    

    (10) 创建oozie.sql文件

    bin/ooziedb.sh create -sqlfile oozie.sql -run
    

    (11) 打包项目 , 生成war包

    bin/oozie-setup.sh prepare-war
    

    (12) Oozie的启动与关闭

    bin/oozied.sh { start | stop }
    

    浏览器访问 oozie 地址 : http://hadoop111:11000/oozie

    案例1 : Oozie调度shell脚本(Shell脚本)

    (1) 创建一个目录存放job任务目录

    mkdir apps
    

    (2) 解压官方案例模板 到 job任务目录 并把examples下的 shell 目录拷贝到 apps

    tar -zxvf oozie-examples.tar.gz
    cp -r examples/apps/shell/ apps/
    

    (3) 拷贝 要执行的脚本 到 job任务目录

    cp test.sh aaps
    

    (4) 修改 job.properties 配置

    # HDFS地址
    nameNode=hdfs://hadoop111:8020
    # ResourceManager地址
    jobTracker=hadoop112:8021
    # 对列名称
    queueName=default
    # 任务根目录
    examplesRoot=apps
    # HDFS上调度执行
    oozie.wf.application.path=${nameNode}/user/${user.name}/${examplesRoot}/shell
    # 脚本名称
    EXEC1=test.sh
    

    (5) 修改 workflow.xml 配置

    <workflow-app xmlns="uri:oozie:workflow:0.4" name="shell-wf">
        <start to="shell-node"/>
        <action name="shell-node">
            <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/dev/apps/shell/${EXEC1}#${EXEC1}</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>
        <end name="end"/>
    </workflow-app>
    

    (6) 上传任务配置

    bin/hadoop fs -put /opt/module/oozie/oozie-4.0.0-cdh5.3.6/apps /user/dev/
    

    (7) 执行任务

    bin/oozie job -oozie http://hadoop111:11000/oozie -config apps/shell/job.properties -run
    

    执行成功后会返回一个 任务id(eg : 0000004-170425105153692-oozie-z-W),如果异常,可以杀死某个任务

    # 杀死某个任务
    bin/oozie job -oozie http://hadoop111:11000/oozie -kill 0000004-170425105153692-oozie-z-W
    

    浏览器中可以查看到 oozie 任务执行情况 & yarn上可以看到mr以及jobhistory详细信息.

    案例2 : Oozie逻辑调度执行多个Job(Shell脚本)

    我这里 apps 目录下创建了一个新目录(shell_more)区分一个job的shell,你在原来基础上改也可以

    (1) 解压官方模板

    (2) 拷贝 examples 下的配置 和 需要执行的脚本

    (3) 修改 job.properties

    # HDFS地址
    nameNode=hdfs://hadoop111:8020
    # ResourceManager地址,端口不要写已经在使用的
    jobTracker=hadoop112:8022
    # 对列名称
    queueName=default
    # 任务根目录
    examplesRoot=apps
    # HDFS上调度执行
    oozie.wf.application.path=${nameNode}/user/${user.name}/${examplesRoot}/shell_more
    # 脚本名称
    EXEC1=test1.sh
    EXEC2=test2.sh
    

    (4) 修改 workflow.xml

    <workflow-app xmlns="uri:oozie:workflow:0.4" name="shell-wf">
        <start to="shell-node1"/>
        <!-- 任务1 -->
        <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>
                <file>/user/dev/apps/shell_more/${EXEC1}#${EXEC1}</file>
                <!-- <argument>my_output=Hello Oozie</argument>-->
                <capture-output/>
            </shell>
            <ok to="shell-node2"/>
            <error to="fail"/>
        </action>
        
    	<!-- 任务2 -->
        <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>
                <file>/user/dev/apps/shell_more/${EXEC2}#${EXEC2}</file>
                <!-- <argument>my_output=Hello Oozie</argument>-->
                <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>
        <end name="end"/>
    </workflow-app>
    

    (5) 上传配置

    bin/hadoop fs -put /opt/module/oozie/oozie-4.0.0-cdh5.3.6/apps/shell_more/ /user/dev/apps/
    

    (6) 执行任务

    bin/oozie job -oozie http://hadoop111:11000/oozie -config apps/shell/job.properties -run
    

    案例3 : Oozie调度MapReduce任务

    (1) 准备一个 MapReduce 任务 jar

    (2) 测试 MapReduce 任务 jar

    (3) 拷贝examples下mr案例到 apps

    cp -r examples/apps/map-reduce/ apps/
    

    (4) 配置map-reduce任务的 job.properties

    nameNode=hdfs://hadoop111:8020
    jobTracker=hadoop112:8032
    queueName=default
    examplesRoot=apps
    #hdfs://hadoop111:8020/user/dev/apps/map-reduce/workflow.xml
    oozie.wf.application.path=${nameNode}/user/${user.name}/${examplesRoot}/map-reduce/workflow.xml
    outputDir=map-reduce
    

    (5) 配置map-reduce任务的 workflow.xml

    <workflow-app xmlns="uri:oozie:workflow:0.2" name="map-reduce-wf">
        <start to="mr-node"/>
        <action name="mr-node">
            <map-reduce>
                <job-tracker>${jobTracker}</job-tracker>
                <name-node>${nameNode}</name-node>
                <prepare>
                    <delete path="${nameNode}/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>/input/</value>
                    </property>
    
                    <!-- 指定输出路径 -->
                    <property>
                        <name>mapred.output.dir</name>
                        <value>/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>
    

    案例4 : Oozie定时任务/循环任务(cron—root用户)

    Coordinator周期性调度任务

    1. 配置Linux时区以及时间服务器,时间服务器配置参考下面大标题 集群时间同步 ,这里忽略时间服务器配置
    date -R
    # 如果不是+0800,删除localtime文件夹,关联一个正确的时区链接
    rm -rf /etc/localtime
    ln -s /usr/share/zoneinfo/Asia/Shanghai /etc/localtime
    
    # ntpdate 域名  #表示同步某个主机时间
    # ntpdate pool.ntp.org
    
    1. 配置 oozie-site.xml 文件

    oozie-default.xml 中有 oozie.processing.timezone 默认配置

    <property>
        <name>oozie.processing.timezone</name>
        <value>GMT+0800</value>
        <description>时区设置东八区</description>
    </property>
    
    1. 修改js框架中的关于时间设置的代码
    function getTimeZone() {
        Ext.state.Manager.setProvider(new Ext.state.CookieProvider());
        return Ext.state.Manager.get("TimezoneId","GMT+0800");
    }
    
    1. 重启oozie服务

    2. 拷贝官方模板配置定时任务

    cp -r examples/apps/cron/ apps/
    
    1. 修改模板 job.properties
    nameNode=hdfs://hadoop111:8020
    jobTracker=hadoop112:8032
    queueName=default
    examplesRoot=apps
    
    oozie.coord.application.path=${nameNode}/user/${user.name}/${examplesRoot}/cron
    # start:必须设置为未来时间,否则任务失败
    start=2020-01-01T21:00+0800
    end=2021-01-01T21:00+0800
    workflowAppUri=${nameNode}/user/${user.name}/${examplesRoot}/cron
    
    EXEC3=test3.sh
    
    1. 修改 coordinator.xml

    注意 : Oozie允许的最小执行任务的频率是 5 分钟

    <!--frequency : 定时cron设置-->
    <coordinator-app name="cron-coord" frequency="${coord:minutes(5)}" start="${start}" end="${end}" timezone="GMT+0800" xmlns="uri:oozie:coordinator:0.2">
    <action>
    	<workflow>
    	    <app-path>${workflowAppUri}</app-path>
    	    <configuration>
    	        <property>
    	            <name>jobTracker</name>
    	            <value>${jobTracker}</value>
    	        </property>
    	        <property>
    	            <name>nameNode</name>
    	            <value>${nameNode}</value>
    	        </property>
    	        <property>
    	            <name>queueName</name>
    	            <value>${queueName}</value>
    	        </property>
    	    </configuration>
    	</workflow>
    </action>
    </coordinator-app>
    
    1. 修改 workflow.xml
    <workflow-app xmlns="uri:oozie:workflow:0.5" name="one-op-wf">
    <start to="shell-node"/>
      <action name="shell-node">
          <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>${EXEC3}</exec>
              <file>/user/dev/apps/cron/${EXEC3}#${EXEC3}</file>
              <!-- <argument>my_output=Hello Oozie</argument>-->
              <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>
    <end name="end"/>
    </workflow-app>
    
    1. 上传配置
    /bin/hdfs dfs -put apps/cron/ /user/admin/apps
    
    1. 启动任务
    bin/oozie job -oozie http://hadoop111:11000/oozie -config apps/cron/job.properties -run
    

    常见问题

    1. Mysql权限配置
    # 授权所有主机可以使用root用户操作所有数据库和数据表
    grant all on *.* to root@'%' identified by '123456';
    flush privileges;
    exit;
    
    1. workflow.xml配置的时候不要忽略file属性

    2. jps查看进程时, 注意有没有bootstrap

    3. 关闭oozie

    ​ 如果bin/oozied.sh stop无法关闭, 则可以使用kill -9 [pid], 之后 oozie-server/temp/xxx.pid 文件一定要删除.

    1. Oozie重新打包时, 一定要注意先关闭进程, 删除对应文件夹下面的pid文件. (可以参考第4条目)

    2. 配置文件一定要生效

    ​ 起始标签和结束标签无对应则不生效, 配置文件的属性写错了, 那么则执行默认的属性.

    1. libext 下边的jar存放于某个文件夹中, 导致share/lib创建不成功.

    2. 调度任务时, 找不到指定的脚本, 可能是 oozie-site.xml 里面的Hadoop配置文件没有关联上.

    3. 修改Hadoop配置文件, 需要重启集群. 一定要记得同步到其他节点.

    4. JobHistoryServer必须开启, 集群要重启的.

    5. Mysql配置如果没有生效的话, 默认使用derby数据库.

    6. 在本地修改完成的job配置, 必须重新上传到HDFS.

    7. 将HDFS中上传的oozie配置文件下载下来查看是否有错误.

    8. Linux用户名和Hadoop的用户名不一致.

    集群时间同步(root用户)

    时间服务器机器设置

    ntp 没有安装就安装一下 yum -y install ntp

    ① vim /etc/ntp.cnf

    # 修改1 打开注释 (表示192.168.1.0 ~ 192.168.1.255网段所有机器可以从这台机器查询和同步时间)
    #restrict 192.168.1.0 mask 255.255.255.0 nomodify notrap
    restrict 192.168.1.0 mask 255.255.255.0 nomodify notrap
    
    #修改2 改为注释掉 (表示不使用互联网上的时间)
    server 0.centos.pool.ntp.org iburst
    server 1.centos.pool.ntp.org iburst
    server 2.centos.pool.ntp.org iburst
    server 3.centos.pool.ntp.org iburst
    #server 0.centos.pool.ntp.org iburst
    #server 1.centos.pool.ntp.org iburst
    #server 2.centos.pool.ntp.org iburst
    #server 3.centos.pool.ntp.org iburst
    
    # 修改3 添加下面2句 (表示时间服务器节点丢失网络连接,可以采用本地时间为集群中其他节点提供时间同步)
    server 127.127.1.0
    fudge 127.127.1.0 stratum 10
    

    ② vim /etc/sysconfig/ntpd

    # 增加 让硬件时间与系统时间一起同步
    SYNC_HWCLOCK=yes
    

    ③ 重启 ntpd 服务

    systemctl restart ntpd
    

    ④ 设置开机启动

    systemctl enable ntpd
    

    其他机器设置(root用户)

    ntp 没有安装就安装一下 yum -y install ntp

    ① 定时更新时间,找时间服务器同步 这里用crontab , 每1分钟同步一次

    */1 * * * * /usr/sbin/ntpdate hadoop111
    

    其实时间同步,也是用Linux自带cron维持,不知道你会不会产生疑问,oozie可以执行cron,为什么不用oozie去同步时间,这个吧,我是这么想的,oozie吧功能是比较齐全,但是它执行定时任务是建立在Linux基础之上(简单点说,oozie只是Linux上一个应用而已)做一个大胆尝试,用oozie去定时调度一个简单的任务,Linux上不停更新时间为过去(意思也就是说,让这个时间永远不再coordinator设置的定时时间范围内), 看下结果是否执行,你就知道oozie和linux之间的关系了…

    所以总结 : 个人认为能用Linux自带的cron定时调度的,就不用第三方应用去处理定时任务

    展开全文

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 2,211
精华内容 884
关键字:

oozie定时调度