Apache Oozie 介绍与核心概念

介绍 Apache Oozie 工作流调度系统:Workflow/Coordinator/Bundle 三层模型、与 Hadoop 集成架构、EL 函数与控制节点、sharelib 共享库机制、5.2.1 终版与 Attic 退役状态说明

Apache OozieOozieApache工作流调度大数据Hadoop2026/10/15

Apache Oozie 介绍与核心概念

目标:介绍 Apache Oozie 工作流调度系统的定位、三层调度模型、与 Hadoop 的集成架构及核心概念,并以 5.2.1 终版(含 Attic 退役状态说明)为基准给出存量运维视角。本文概念均已在 Ubuntu 22.04 + Oozie 5.2.1 + Hadoop 3.3.6 + MySQL 8.0.46 环境实测验证(workflow 与 coordinator 均跑通 SUCCEEDED)。

一、环境信息

本文所述概念与引用的命令回显来自以下实测环境,读者对照操作时输出可能略有差异。

项目值
操作系统Ubuntu 22.04(主机名 oozie,内网 IP 172.17.0.15)
Oozie 版本5.2.1(2021-02-25 发布,源码构建,-Phadoop-3 -Dhadoop.version=3.3.6)
Hadoop 版本3.3.6(伪分布式)
元数据库MySQL 8.0.46(oozie 库,12 张表)
JDKOpenJDK 1.8.0_504
Maven3.6.3(源码构建用)
实测结果workflow 0000000-261014183638552-oozie-root-W SUCCEEDED;coordinator 0000001-261014183638552-oozie-root-C SUCCEEDED

💡 说明:Oozie 是有独立服务进程(Java/Jetty)的服务端组件,默认监听 11000 端口;客户端通过 oozie CLI 或 REST API 与服务端交互。上表中 workflow/coordinator ID 的中段 261014183638552 是服务启动时间戳,oozie-root 来自配置项 oozie.system.id,尾缀 W/C 分别代表 Workflow 与 Coordinator 类型作业。

二、软件概述

2.1 项目定位

Apache Oozie 是一个面向 Hadoop 生态的工作流调度系统(Workflow Scheduler),用于把多个 Hadoop 作业(MapReduce、Hive、Pig、Sqoop、Spark、Shell 等)按有向无环图(DAG)组织成工作流,并支持按时间/数据到达条件周期性触发,解决「大数据任务依赖编排 + 定时调度」问题。它由服务端(Oozie Server,War 式 Web 应用,5.x 起内嵌 Jetty 运行)、关系型元数据库(默认 Derby,生产常用 MySQL/PostgreSQL)与客户端 CLI 组成;工作流定义(workflow.xml)、Coordinator 定义与应用包存放于 HDFS。

Oozie 于 2012 年 8 月成为 Apache 顶级项目(Top Level Project),是 Hadoop 1.x/2.x 时代事实上的标准调度组件,广泛存在于 CDH/HDP 等企业发行版中。

2.2 ⚠️ 退役状态(Apache Attic):2025 年 2 月退役、2025 年 4 月迁入

Apache Oozie 已于 2025 年 2 月经董事会决议退役,2025 年 4 月完成迁移至 Apache Attic(退休项目馆)。 Attic 官方页面原文:

"Oozie became a Top Level Project in August 2012, retired in February 2025 and the move to the Attic was completed in April 2025."

即:Oozie 2012 年 8 月成为顶级项目,2025 年 2 月退役,2025 年 4 月完成迁入 Attic(页面:https://attic.apache.org/projects/oozie.html)。

退役对使用者的直接含义:

维度现状
最终版本5.2.1(2021-02-25 发布),不会再有新版本与官方补丁
下载渠道仅 Apache 归档 https://archive.apache.org/dist/oozie/5.2.1/,且只有源码包 oozie-5.2.1.tar.gz(2.7M)
官方文档https://oozie.apache.org/docs/5.2.1/ 仍在线可访问(Attic 项目文档保留)
安全修复无官方安全更新,生产使用需自行评估风险
适用视角存量运维:已有 Oozie 集群的维护、迁移评估;新项目建议选型替代品(见「六、同类选型对比」)

⚠️ 注意:正因为已退役,互联网上大量旧教程描述的「下载 oozie-sharelib-x.x.x.tar.gz / ext-2.2.zip / 执行 prepare-war」等流程与 5.2.1 的真实发行形态不符。5.2.1 的正确认知见 2.3 节。

2.3 版本与发行形态(5.2.1 关键事实)

Oozie 5.2.1 的发行形态与 4.x 时代有显著差异,以下事实均已实测核实:

  1. 只有源码包:官方归档 https://archive.apache.org/dist/oozie/5.2.1/ 目录真实内容为:

    oozie-5.2.1.tar.gz         2021-02-25 16:31  2.7M
    oozie-5.2.1.tar.gz.asc     2022-07-18 12:47  833
    oozie-5.2.1.tar.gz.asc.txt 2021-02-25 16:31  833
    oozie-5.2.1.tar.gz.sha512  2021-02-25 16:31  204
    rat_report.txt             2021-02-25 16:31  139K
    release-log.txt            2021-02-25 16:31  157K
    

    不存在 oozie-sharelib-5.2.1.tar.gz、ext-2.2.zip 之类的二进制发布物。二进制发行包必须用源码内 bin/mkdistro.sh 自行构建(官方 ENG_Building 原文:"The simplest way to build Oozie is to run the mkdistro.sh script",且 "IMPORTANT: Profile hadoop-3 must be activated if building against Hadoop 3")。

  2. sharelib 是构建产物:官方 AG_Install 原文称 sharelib TAR.GZ "bundled with the distribution"——它由 mkdistro 构建时生成,随发行包自带(实测发行包内确有 oozie-sharelib-5.2.1.tar.gz),无需另行下载。

  3. ext-2.2.zip 从未随 Apache 发布:WebUI 依赖的 ExtJS 2.2 库(文件名固定 ext-2.2.zip)从未由 Apache 发布,需要自行获取(官方 AG_Install 原文:"If the ExtJS ZIP file is present in the libext/ directory, it will be added to the Jetty's webapp/ directory as well. The ExtJS library file name be ext-2.2.zip.")。实测可用的存活来源是 Cloudera gplextras 归档 https://archive.cloudera.com/gplextras/misc/ext-2.2.zip(6,800,612 字节)。

  4. 5.x 内嵌 Jetty,无需 Tomcat,无 prepare-war:Oozie 5.x 默认内嵌 Jetty(9.3.20.v20170531),发行包自带 embedded-oozie-server/ 目录(预展开的 webapp,WEB-INF/lib/ 含 264 个 jar)。oozie-setup.sh 已无 4.x 时代的 prepare-war 子命令,实测 --help 回显只有 sharelib create/upgrade、db create/upgrade/postupgrade、export/import。

💡 技术拓展:工作流引擎的「服务端承载方式」不止一种,同类选择对比——

方式原理/特点适用场景
独立 War + Tomcat打 War 包部署到外部 Tomcat 服务器Oozie 4.x 及更早版本的做法
内嵌 Jetty应用自带 Jetty 直接运行,少一层外部依赖Oozie 5.x(含 5.2.1)采用此方式,部署更简单
微服务内嵌(Spring Boot 式)可执行 jar 自带 HTTP 服务新一代调度器(如 DolphinScheduler)的常见形态

Oozie 5.2.1 采用内嵌 Jetty,因此安装时不需要单独下载 Tomcat,也不再有 prepare-war 步骤。

2.5 服务状态实测

Oozie 服务启动后,用 oozie admin -status 可确认服务健康(本环境实测回显):

export OOZIE_URL=http://localhost:11000/oozie
/opt/oozie-5.2.1/bin/oozie admin -status
System mode: NORMAL

对应的 REST API(实测):

curl -s http://localhost:11000/oozie/v2/admin/status
{"systemMode":"NORMAL"}

System mode: NORMAL 表示 Oozie 服务正常运行并可接受作业提交;若为 SAFEMODE 等其他模式则说明服务受限。

三、核心架构

3.1 总体组件

Oozie 的运行时架构由五部分组成,各组件职责与实测落点如下:

组件职责本环境实测落点
Oozie Server接收作业提交、解析 workflow/coordinator 定义、调度状态机、写元数据库/opt/oozie-5.2.1,bin/oozied.sh start 启动,监听 11000
内嵌 Jetty承载 WebUI 与 REST API 的 HTTP 服务发行包 embedded-oozie-server/(webapp 预展开,264 个 jar)
元数据库存储作业定义、实例状态、动作状态、SLA 数据MySQL 8.0.46 的 oozie 库(12 张表,见 3.3)
HDFS sharelib各 action 类型运行所需的公共 jar 库,作业按 oozie.use.system.libpath=true 自动加载/user/root/share/lib/lib_20261014181925(oozie-setup.sh sharelib create 上传)
Hadoop 集群工作流动作的真正执行者(YARN 资源调度 + MapReduce/Hive 等计算)Hadoop 3.3.6 伪分布式(NameNode/DataNode/ResourceManager/NodeManager/JobHistoryServer)

服务端通过 oozie.service.HadoopAccessorService.hadoop.configurations(实测值 *=/opt/hadoop/etc/hadoop)指向 Hadoop 配置目录,从而以「代理用户」身份操作 HDFS/YARN——这也是 Hadoop 侧 core-site.xml 必须配置 hadoop.proxyuser.root.hosts/groups 的原因(本环境以 root 运行,实测配置为 *)。

3.2 launcher job:Oozie 与 YARN 的桥梁

Oozie 服务端本身不直接执行业务计算。提交 workflow 的 action 时,服务端先向 YARN 提交一个 launcher MapReduce 作业(只有 Mapper、无 Reduce 的轻量作业),由 launcher 进程在集群内拉起真正的业务逻辑(如 MR 作业、Hive CLI 等)。服务端轮询 launcher 的状态并回写元数据库。

实测 oozie job -log 中的关键日志可以印证这条链路:

2026-10-14 18:36:53,537  INFO MapReduceActionExecutor:520 - ... ACTION[...-W@mr-node] Starting action. Getting Action File System
2026-10-14 18:36:54,386  INFO MapReduceActionExecutor:520 - ... checking action, hadoop job ID [application_1791998675123_0003] status [RUNNING]

application_1791998675123_0003 就是 YARN 上的 launcher/业务作业;oozie job -info 输出中 action 的 Ext ID(External ID)即指向该 YARN application。实测 workflow 的 mr-node 动作 Ext ID 为 application_1791998675123_0003,Ext Status 为 SUCCEEDED。

3.3 元数据库与数据表

Oozie 把所有作业与调度的持久状态写入元数据库。实测 MySQL oozie 库在完成建库、部署与一次 workflow/coordinator 运行后的 12 张表:

BUNDLE_ACTIONS, BUNDLE_JOBS, COORD_ACTIONS, COORD_JOBS, OOZIE_SYS,
OPENJPA_SEQUENCE_TABLE, SLA_EVENTS, SLA_REGISTRATION, SLA_SUMMARY,
VALIDATE_CONN, WF_ACTIONS, WF_JOBS

核心表含义:

表名含义
WF_JOBS / WF_ACTIONSworkflow 作业实例与动作实例状态
COORD_JOBS / COORD_ACTIONScoordinator 作业与已实体化的 coordinator 动作
BUNDLE_JOBS / BUNDLE_ACTIONSbundle 作业与其下属 coordinator 动作
SLA_REGISTRATION / SLA_SUMMARY / SLA_EVENTSSLA 规则注册、达成汇总与事件
OOZIE_SYS系统级元数据(版本标识等)
OPENJPA_SEQUENCE_TABLEOpenJPA 主键序列
VALIDATE_CONN连接校验辅助表

实测数据落库证据:3 次 map-reduce 提交 + 1 个 no-op 实例使 SELECT COUNT(*) FROM oozie.WF_JOBS; 返回 4;SELECT COUNT(*) FROM oozie.COORD_JOBS; 返回 1。

JDBC 连接串(实测配置,官方 AG_Install 建议 GMT 时区参数规避夏令时问题):

jdbc:mysql://127.0.0.1:3306/oozie?useLegacyDatetimeCode=false&serverTimezone=GMT

3.4 WebUI 控制台

Oozie 自带基于 ExtJS 2.2 的 Web 控制台(http://<host>:11000/oozie/),可查看作业列表、状态与 DAG。ExtJS 库并不随发行包携带,需将 ext-2.2.zip 放入 libext/ 后由 oozie-setup.sh 解入 webapp。实测验证方式(三项均通过):

curl -s -o /dev/null -w "%{http_code}" http://localhost:11000/oozie/index.jsp
200
curl -s http://localhost:11000/oozie/index.jsp | grep -o "<title>[^<]*</title>"
<title>Oozie Web Console</title>
curl -s -o /dev/null -w "HTTP %{http_code}, %{size_download} bytes" http://localhost:11000/oozie/ext-2.2/ext-all.js
HTTP 200, 538956 bytes

⚠️ 注意:若 /oozie/ext-2.2/* 返回 404,说明 ext-2.2.zip 未合入 webapp,WebUI 会白屏(仅剩工具栏)。这是判断 ExtJS 是否就位的客观检查点。

四、功能特性

4.1 三层调度模型总览

Oozie 用三层模型覆盖「单次编排 → 周期调度 → 批量编排」:

层级定义文件触发方式典型用途本环境实测
Workflowworkflow.xml(uri:oozie:workflow:1.0)提交即运行一次把一组 Hadoop 作业编排成 DAG0000000-…-W SUCCEEDED
Coordinatorcoordinator.xml(uri:oozie:coordinator:0.2)按频率(cron/时间单元)+ 数据可用性周期触发 workflow日报/小时任务、数据就绪触发0000001-…-C SUCCEEDED
Bundlebundle.xml(uri:oozie:bundle:0.2)批量提交/统一管控多个 coordinator多条管道的成组启停结构记录,未实测运行

三层为包含关系:Bundle 管理多个 Coordinator,Coordinator 周期性实例化 Workflow。三层作业 ID 后缀分别为 W、C、B(实测 workflow …-oozie-root-W、coordinator …-oozie-root-C)。

4.2 Workflow:action 节点与控制节点

Workflow 是以 DAG 表达的有向无环图,定义在 HDFS 上的 workflow.xml 中,根元素 <workflow-app name="..." xmlns="uri:oozie:workflow:1.0">。节点分两类:

类别节点作用
控制节点<start to="..."/>工作流入口,指定第一个节点
控制节点<end name="..."/>成功终点
控制节点<kill name="..."><message>...</message></kill>失败终止,message 支持 EL
控制节点<decision name="..."><switch>...</switch></decision>按 EL 表达式条件分支
控制节点<fork name="..."> / <join name="..."/>并行分支与汇合
动作节点<action name="...">执行具体任务(map-reduce/fs/java/hive2/pig/sqoop/spark/shell/email/sub-workflow 等官方支持的 action 类型)

每个 action 节点必须声明两条转移:<ok to="节点名"/>(成功去向)与 <error to="节点名"/>(失败去向),失败通常指向 kill 节点。实测示例(发行包 examples 的 map-reduce workflow 关键结构):

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

💡 说明:5.2.1 的 workflow 1.0 schema 用 <resource-manager> 元素指定 YARN ResourceManager(不再是 4.x 时代的 <job-tracker>),<name-node> 指定 NameNode;两者通常用 ${resourceManager}/${nameNode} 参数占位,由 job.properties 注入实际值。

4.3 Workflow 生命周期(状态机)

一个 workflow 作业实例(Workflow Job)在数据库中的状态遵循 HAL(Hadoop Application Layer)生命周期,官方定义的状态集合:

状态含义
PREP已创建、尚未开始执行首个节点
RUNNING正在执行节点流转
SUSPENDED被挂起(可恢复)
SUCCEEDED全部节点成功结束
KILLED被 oozie job -kill 或错误终止
FAILED执行失败终止

实测观察:服务端缺 YARN 客户端 jar 时,提交后的 workflow 卡在 RUNNING 且其 mr-node 动作长期 PREP(动作级状态),补齐依赖重启后再次提交即正常流转至 SUCCEEDED——状态既体现在 oozie job -info 输出中,也持久化在 WF_JOBS/WF_ACTIONS 表里。

4.4 Coordinator:时间与数据触发

Coordinator 把同一个 workflow 按频率周期性实例化。定义文件 coordinator.xml(实测使用的 0.2 schema)核心要素:

  • frequency:触发频率。0.2+ schema 支持 cron 表达式(实测 0/10 * * * *,每 10 分钟一个 nominal time),更早 schema 用 frequency + timeunit(如 frequency="1" start="..." end="...")表达。
  • start / end / timezone:起止时间与时区。使用 cron 频率时 timezone 必填(实测 timezone="UTC",nominal time 按 UTC 生成)。
  • <action><workflow><app-path>:指向被调度的 workflow 应用 HDFS 路径,并可通过 <configuration> 向 workflow 传参。
  • 动作实体化(materialization):服务端按频率把 startend 区间切分成一个个 nominal time,逐个生成 coordinator action(存入 COORD_ACTIONS 表),到点触发 workflow 实例。实测 0000001-…-C 在 18:4018:50(UTC)区间内只生成并成功执行了 1 个动作 C@1,其 Ext ID 指向 workflow 实例 0000002-…-W。

💡 技术拓展:Coordinator 的「频率表达」有两种形式,适用对比——

形式写法示例特点适用场景
frequency + timeunitfrequency="60" 配 timeunit(minute/hour/day/week 等)语义简单,从 start 时间起算等间隔固定周期任务
cron 表达式frequency="0 0 1 * *"(0.2+ schema)可表达「每天 1 点」等锚定时刻,timezone 必填日报类、跨时区精确时刻

本环境实测采用 cron 形式(0/10 * * * * + timezone="UTC")验证调度闭环。

除时间触发外,Coordinator 还支持 dataset(数据集)+ 初始实例 的数据可用性触发模型:把 HDFS 上按时间分区的输入目录(如 /input-data/${YEAR}${MONTH}${DAY})声明为 <dataset>,action 用 <data-in> 引用并在数据实例就绪时才触发——该模型属于官方 Coordinator 功能集,本环境未实测运行(实测走的是 cron 触发),使用时以官方 CoordinatorFunctionalSpec 为准。

4.5 Bundle:批量编排

Bundle 是最高一层编排单元(uri:oozie:bundle:0.2),把多个 coordinator 聚合成一个作业统一提交、挂起与终止。核心结构为 <controls><kick-off-time> 加若干 <coordinator name="..."><app-path>...</app-path><configuration> 子块,可在 configuration 中为每个 coordinator 注入 start/end 等参数。提交命令与 coordinator 相同(oozie job -config bundle.properties -run)。bundle 的状态持久化在 BUNDLE_JOBS/BUNDLE_ACTIONS 表(本环境 12 张表中已含此二表)。

4.6 EL 函数与参数化

Oozie 用 EL(Expression Language)实现定义与环境的解耦,$ 加花括号包裹的变量在提交时由 job.properties 赋值,函数调用则在运行期求值。实测 workflow 中出现的两类用法:

  1. 参数占位:${resourceManager}、${nameNode}、${queueName}、${outputDir} 等,值来自提交时指定的 job.properties;
  2. 内置函数:${wf:user()}(返回提交用户,实测解析为 root,用于拼接 HDFS 输入/输出路径)、${wf:errorMessage(wf:lastErrorNode())}(kill 消息中取最后一个失败节点的错误信息)。

常用 workflow EL 函数(官方 WorkflowFunctionalSpec 定义)速览:

函数含义
wf:id()当前 workflow 作业 ID
wf:name()workflow 名称
wf:user()提交用户
wf:conf(String)读 job.properties 中的配置
wf:lastErrorNode()返回最后一个出错节点名
wf:errorCode(String) / wf:errorMessage(String)取节点的错误码/错误信息
wf:actionExternalId(String)取指定动作的外部作业 ID
wf:actionExternalStatus(String)取指定动作的外部状态

参数化的载体 job.properties 是纯键值文件,除业务参数外还包含 Oozie 指令型键(如实测用到的 oozie.use.system.libpath=true 开启 sharelib 加载、oozie.wf.application.path=${nameNode}/user/${user.name}/${examplesRoot}/apps/map-reduce 指定 workflow 应用在 HDFS 的路径)。

4.7 sharelib 共享库机制

sharelib(共享库)是 Oozie 预先上传到 HDFS 的公共 jar 集,供 hive/pig/sqoop/spark 等 action 运行时按类型加载,避免把依赖打进每个应用。机制要点(均实测):

  • 由 oozie-setup.sh sharelib create -fs hdfs://oozie:9000 上传,生成带时间戳的版本目录(实测 /user/root/share/lib/lib_20261014181925);
  • 上传时自动对 /user/root/share/lib 关闭 Hadoop 纠删码(实测日志:"Found Hadoop that supports Erasure Coding. Trying to disable Erasure Coding for path: /user/root/share/lib");
  • 作业侧用 oozie.use.system.libpath=true 声明加载系统 sharelib(实测 map-reduce 与 no-op 示例均如此);
  • 升级 sharelib 用 sharelib upgrade 子命令(oozie-setup.sh --help 实测可见),新旧版本目录并存便于回退。

4.8 SLA 与通知

Oozie 内置 SLA(Service Level Agreement)跟踪:workflow/coordinator/bundle 定义中可注册「应在何时开始/结束」的预期,超时情况记录在 SLA_REGISTRATION/SLA_SUMMARY/SLA_EVENTS 三张表(本环境建库后即存在)。作业动作还支持 notification URL(工作流状态变化时回调通知);实测日志中可见该机制处于待配置状态:"No Notification URL is defined. Therefore nothing to notify for job …"。

五、适用场景与限制

适用场景(结合 5.2.1 存量运维视角):

  1. 已有 Oozie 集群的日常维护:查看/重跑/补数历史 workflow 与 coordinator;
  2. Hadoop 2.x/3.x 集群上已经固化的 MR/Hive/Pig/Sqoop 作业链编排,迁移成本高于维护成本时的延续运行;
  3. 需要「数据就绪触发 + 时间触发」混合调度、且不愿引入新组件的老集群;
  4. 作为调度器迁移(至 Airflow/DolphinScheduler 等)前的行为基线与回退保障。

限制与风险(退役后尤为突出):

  1. 无官方安全补丁,暴露公网前必须自行加固(鉴权默认关闭,实测配置 oozie.service.AuthorizationService.authorization.enabled=false);
  2. 仅源码发行,二进制须自行构建,构建环境(JDK8 + Maven + Hadoop profile)门槛高,且存在历史依赖死链问题(如 txw2 死版本只能本地植入);
  3. WebUI 依赖的 ExtJS 2.2 极旧,仅作历史作业查看,无现代交互能力;
  4. 对 Hadoop 3 客户端依赖不全(-Phadoop-3 构建的 webapp 缺 mapreduce/yarn 客户端 jar),需要手工补齐(安装指南有完整排障链);
  5. 生态新特性(如 Kerberos 细化、新 action 类型)不再演进。

六、同类选型对比

💡 技术拓展:工作流调度器不止 Oozie 一种,面向 Hadoop 或通用数据管道的主流同类对比——

组件定位编排表达依赖体系现状
OozieHadoop 生态专用调度器workflow.xml(XML DAG)+ coordinator/bundle强绑定 Hadoop,Java 栈2025-02 退役,仅存量运维
Apache Airflow通用数据编排平台Python DAG 代码Python 生态,组件丰富活跃,社区最大
Apache DolphinScheduler分布式可视化工作流拖拽 DAG + 多租户去 Hadoop 绑定,Java 栈活跃,国产主导
AzkabanLinkedIn 批处理调度器properties + job 文件轻量但演进缓慢低活跃

新建调度系统不建议再选 Oozie(无安全更新、仅源码发行);存量系统若编排逻辑复杂、Hive/Pig 依赖深,可短期维持 Oozie 并规划向 Airflow/DolphinScheduler 迁移。迁移视角上:Oozie 的 workflow.xml 节点模型(action/ok/error 转移)与 Airflow 的 task + dependency、DolphinScheduler 的任务节点连线概念可一一映射;coordinator 的 cron 频率与两者的调度表达式语义等价,迁移的主要工作量在 EL 函数(${wf:user()} 等)与参数传递方式的改写。

七、参考链接