为文件的每一行执行一个子工作流



我正在使用Oozie Sqoop Action在Datalake中导入数据。我需要数据库源的每个表都有一个HDFS文件夹。我有300多张桌子。

我可以将所有300个Sqoop操作硬编码在工作流中,但工作流对于Oozie配置来说太大了。

Error submitting job /user/me/workflow.xml
E0736: Workflow definition length [107,123] exceeded maximum allowed length [100,000]

拥有这样的大文件不是一个好主意,因为它会减慢系统的速度(它保存在数据库中),而且很难维护。

问题是,如何为每个表名称调用子工作流

等效的shell脚本类似于:

while read TABLE; do
  sqoop import --connect ${CONNECT} --username ${USERNAME} --password ${PASSWORD} --table ${TABLE} --target-dir ${HDFS_LOCATION}/${TABLE} --num-mappers ${NUM-MAPPERS}
done < tables.data

其中tables.data包含一个表名列表,该列表是数据库源表名的子集。例如:

TABLE_ONE
TABLE_TWO
TABLE_SIX
TABLE_TEN

这里是我想为每个表调用的子工作流:

<workflow-app name="sub-workflow-import-table" xmlns="uri:oozie:workflow:0.5">
    <start to="sqoop-import"/>
    <action name="sqoop-import">
        <sqoop xmlns="uri:oozie:sqoop-action:0.2">
            <job-tracker>${jobTracker}</job-tracker>
            <name-node>${nameNode}</name-node>
            <command>sqoop import --connect ${CONNECT} --username ${USERNAME} --password ${PASSWORD} --table ${TABLE} --target-dir ${HDFS_LOCATION}/${TABLE} --num-mappers ${NUM-MAPPERS}</command>
        </sqoop>
        <ok to="end"/>
        <error to="log-and-kill"/>
    </action>
    <end name="end"/>
    <kill name="log-and-kill">
        <message>Workflow failed, error message[${wf:errorMessage(wf:lastErrorNode())}]</message>
    </kill>
</workflow-app>

如果您需要更精确的信息,请告诉我。谢谢David

遗憾的是,在Oozie中没有办法很好地做到这一点——您需要将所有300个Sqoop操作硬编码到Oozie XML中。这是因为Oozie处理的是有向无环图,这意味着循环(比如你的shell脚本)没有等价的Oozie。

然而,我不认为Oozie是正确的工具。Oozie需要每个操作一个容器来用作启动器,这意味着集群需要在一次运行的空间内分配300个额外的容器。这可以有效地使集群死锁,因为您最终会遇到启动器阻止实际作业运行的情况!我曾经处理过一个有1000多个表的大型集群,我们在那里使用了Bash来避免这个问题。

如果你真的想在Oozie中继续这样做,你无法避免生成一个包含300个操作的工作流。我会将其作为300个操作来执行,而不是对每个子工作流调用一个操作的300个调用,否则您将产生更多的开销。您可以手动创建这个文件,或者最好编写一些代码来生成给定表列表的Oozie工作流XML文件。后者更灵活,因为它允许在每次运行的基础上包含或排除表。

但正如我最初所说,除非你有一个非常好的理由,否则我会坚持Bash。

我的建议是为每个50个表的导入创建工作流。所以你有6个这样的。从主工作流或父工作流中调用所有6个工作流作为子工作流。通过这种方式,我们可以在某一点上进行控制,并且可以很容易地安排单个工作流。

相关内容

最新更新