【译】CDH5 中 Apache Oozie sharelib 的使用

Oozie 的 ShareLib 内部已经发生变化,从 CDH 5.0.0 开始,以下是你需要知道的

在一年前的这篇博客,我介绍了如何在 CDH 4 中使用的 Apache Oozie ShareLib。但是 ShareLib 在 CDH 5 发生了变化,尤其是目录结构,之前提及的一些内容现在已经过时了(这些变动在 OOZIE-1619 可以看到)。

目录结构变化

在 CDH 4.x 中,ShareLib 的目录结构类似下面:

1
2
3
/user/oozie/share/lib/distcp/*.jar
/user/oozie/share/lib/hive/*.jar
/user/oozie/share/lib/...

但是在 CDH 5.x 中,目录新增了一个层级,包含了一个时间戳

1
2
3
/user/oozie/share/lib/lib_20140311155426/distcp/*.jar
/user/oozie/share/lib/lib_20140311155426/hive/*.jar
/user/oozie/share/lib/lib_20140311155426/...

ShareLib 的位置仍然像之前那样通过 oozie.service.WorkflowAppService.system.libpath 配置参数指定。lib_<timestamp> 目录会被创建在该目录下,如上面示例所示。

如你猜想的那样,实际上可能会出现多个 lib_<timestamp> 这样的目录,就像上面示例中的一样,时间戳的格式是 yyyymmddhhmmss 。主要原因是为了解决以下的情况:

假设你有一些作业正在运行且使用到了 ShareLib,你打算更新 ShareLib 却不想等到所有这些作业完成了才去操作。在以前(CDH 4.x),进行这样的操作会导致作业失败,因为会导致分布式缓存混乱。但是使用新的目录结构,这样的事情就不会发生——已经运行的作业会继续使用旧的 ShareLib,而新启动的作业将使用最新的 ShareLib。在启动时,Oozie 将查找最新的 lib_<timestamp> 目录并使用。

新 ShareLib 目录结构的另一个好处是,我们无需重启 Oozie 即可完成 ShareLib 的更新,在后面将会详述。

这是 CDH 5.0.0 中 ShareLib 作为参考。除了版本号以及 lib_<timestamp> 目录,看起来与 CDH 4.1.2 的比较相似

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
drwxr-xr-x share/lib/lib_20140403151601/distcp
-rw-r--r-- share/lib/lib_20140403151601/distcp/hadoop-distcp-2.3.0-cdh5.0.0.jar
-rw-r--r-- share/lib/lib_20140403151601/distcp/oozie-sharelib-distcp-4.0.0-cdh5.0.0.jar
drwxr-xr-x share/lib/lib_20140403151601/hcatalog
-rw-r--r-- share/lib/lib_20140403151601/hcatalog/ST4-4.0.4.jar
-rw-r--r-- share/lib/lib_20140403151601/hcatalog/ant-1.8.1.jar
-rw-r--r-- share/lib/lib_20140403151601/hcatalog/ant-launcher-1.8.1.jar
-rw-r--r-- share/lib/lib_20140403151601/hcatalog/avro-1.7.5-cdh5.0.0.jar
-rw-r--r-- share/lib/lib_20140403151601/hcatalog/avro-ipc-1.7.5-cdh5.0.0-tests.jar
-rw-r--r-- share/lib/lib_20140403151601/hcatalog/avro-ipc-1.7.5-cdh5.0.0.jar
-rw-r--r-- share/lib/lib_20140403151601/hcatalog/avro-mapred-1.7.5-cdh5.0.0.jar
-rw-r--r-- share/lib/lib_20140403151601/hcatalog/bonecp-0.7.1.RELEASE.jar
-rw-r--r-- share/lib/lib_20140403151601/hcatalog/commons-compress-1.4.1.jar
-rw-r--r-- share/lib/lib_20140403151601/hcatalog/commons-httpclient-3.1.jar
-rw-r--r-- share/lib/lib_20140403151601/hcatalog/commons-io-2.1.jar
-rw-r--r-- share/lib/lib_20140403151601/hcatalog/datanucleus-api-jdo-3.2.1.jar
-rw-r--r-- share/lib/lib_20140403151601/hcatalog/datanucleus-core-3.2.2.jar
-rw-r--r-- share/lib/lib_20140403151601/hcatalog/datanucleus-rdbms-3.2.1.jar
-rw-r--r-- share/lib/lib_20140403151601/hcatalog/groovy-all-2.1.6.jar
-rw-r--r-- share/lib/lib_20140403151601/hcatalog/hive-ant-0.12.0-cdh5.0.0.jar
-rw-r--r-- share/lib/lib_20140403151601/hcatalog/hive-common-0.12.0-cdh5.0.0.jar
-rw-r--r-- share/lib/lib_20140403151601/hcatalog/hive-exec-0.12.0-cdh5.0.0.jar
-rw-r--r-- share/lib/lib_20140403151601/hcatalog/hive-hcatalog-core-0.12.0-cdh5.0.0.jar
...

Oozie 会自动清理旧的 ShareLib lib_<timestamp> 目录,基于以下两条规则:

  • 超过ShareLibService.temp.sharelib.retention.days 指定的天数,默认7天
  • 保留最新的两个时间点的目录

如今,Oozie 已经支持自动检查目录的状态并清理(译者:原文作者在撰写本博客时该特性未支持,截至现在已经支持 OOZIE-1783,译者此处予以修改)。这也意味着,你可以安全的从 HDFS 删除旧的 lib_<timestamp> 目录。对于大多数 CDH 用户,通常仅仅在升级 CDH 版本的时候才会去更新 ShareLib,这里应该不会是一个大的问题。

安装方式变化

在 CDH 4.x 中,安装方式主要就是解压 ShareLib 的 压缩包,然后将它上传到 HDFS /user/oozie/share/lib 的这个目录下。

在 CDH 5.0.0 中,我们可以通过脚本进行安装,同时这是推荐的安装方式。脚本帮你完成 ShareLib 压缩包的解压,lib_<timestamp> 目录的创建,并上床到 HDFS。这非常重要:简单的上传 ShareLib 到 /user/oozie/share/lib 将不再有效,因为 Oozie 将找不到这些 jar 包。

可以通过以下命令,使用到这个脚本

1
oozie-setup sharelib create -fs FS_URI [-locallib SHARED_LIBRARY]

FS_URI 是 ShareLib 将要安装到 HDFS 的 URI 路径(例如:hdfs://<HOST><PORT>),而可选的 SHARED_LIBRARY 指的是需要安装的 ShareLib 安装包。通常脚本能够自行为你查找安装的 ShareLib 安装包,但是如果你需要特别指定安装包(如:MRv1版本),你可以配置这个参数。

若从 CDH 4.x 升级到 CDH 5.x,我们推荐你先手动删除 ShareLib,这样 CDH 4.x 的 jar 就不会存在到目录了

有用的命令以及信息

我们也新增了一些方式来获取 ShareLib 的信息

admin -shareliblist 命令可以用来列出 ShareLib 的内容,而无需自己到 HDFS 查找 Oozie 当前正在使用的 ShareLib。例如:

1
2
3
4
5
6
7
8
9
10
$ oozie admin -shareliblist
[Available ShareLib]
oozie
hive
distcp
hcatalog
sqoop
mapreduce-streaming
hive2
pig

你也可以像这样获取每一个 ShareLibs 的 jar 列表

1
2
3
4
5
6
7
$ oozie admin -shareliblist pig
[Available ShareLib]
pig
hdfs://rkanter-has-1.ent.cloudera.com:8020/user/oozie/share/lib/lib_20140403151601/pig/ant-1.6.5.jar
hdfs://rkanter-has-1.ent.cloudera.com:8020/user/oozie/share/lib/lib_20140403151601/pig/antlr-2.7.7.jar
hdfs://rkanter-has-1.ent.cloudera.com:8020/user/oozie/share/lib/lib_20140403151601/pig/antlr-runtime-3.4.jar
...

我之前提到的,你可以在 Oozie 正在运行的时候更新 ShareLib,通过 admin -sharelibupdate 命令

1
2
3
4
5
6
$ oozie admin -sharelibupdate
[ShareLib update status]
host = rkanter-has-1.ent.cloudera.com:11000
status = Successful
sharelibDirOld = hdfs://rkanter-has-1.ent.cloudera.com:8020/user/oozie/share/lib/lib_20140403151601
sharelibDirNew = hdfs://rkanter-has-1.ent.cloudera.com:8020/user/oozie/share/lib/lib_20140425150458

如你看到的,这会让 Oozie 自动切换到最新的 lib_<timestamp> 目录。这个命令同样在 Oozie HA 模式有效,你只需要运行该命令一次,每一个 Oozie server 都会查找最新的 ShareLib。

Overriding ShareLib

虽然我在之前的博客中已经提及过,但是我还是想再说一下。如果你想要改变 Oozie 使用的 ShareLib,或者有多个 ShareLib 且针对不同的 Action 使用不同的 ShareLib,你可以通过 Overriding ShareLib 实现.

你或许注意到目前已经有一个 hcatlog 的 ShareLib,这里并没有一个新的 HCat Action。这是为了方便那些想要连接到 Hcat 而需要 HCatlog jar 包的 Action,一个常见的用例是一个 Pig Action 中需要连接到 HCatlog。你可以通过 oozie.action.sharelib.for.#ACTIONTYPE# 配置来 overriding 某种类型的 Action 的 ShareLib。这个配置可以放到 Action 的 <configuration>job.properties 或者 oozie-site.xml ,并且配置的优先级也按照这个顺序。

例如,如果你希望你的某个工作流中的所有 Pig Action 都包含 HCatlog 这个 ShareLib,你可以添加 oozie.action.sharelib.for.pig=pig,hcatlog 到你的 job.properties 当中。

ShareLib 映射文件

另一个新的功能是可以通过映射文件配置 ShareLib 的位置,而不是使用 oozie.service.WorkflowAppService.system.libpath 中配置的位置。映射文件的位置可以在 oozie-site.xml 中的 oozie.service.ShareLibService.mapping.file 中配置,这个配置文件应当是包含一系列的 =

1
2
3
oozie.pig_10=hdfs:///share/lib/pig/pig-0.10.1/lib/
oozie.pig=hdfs:///share/lib/pig/pig-0.11.1/lib/
oozie.distcp=hdfs:///share/lib/hadoop-2.2.0/share/hadoop/tools/lib/hadoop-distcp-2.2.0.jar

需要注意的是,这是一个高级功能并且是可选配置。对于大多数使用者应该使用前面提到的 ShareLib 目录,而不是使用映射文件。

最后一点

对于如何在工作流中导入其他的 jar 包,我看到不少人对此感到困惑。借此机会,我对这方面做下说明,以下是一些在工作流中导入其他 jar 包的可选方案:

  • 配置 oozie.libpath=/path/to/jars,another/path/to/jarsjob.properties
    • 如果你有多个工作流都需要相同的 jar 包,那么这种方式比较好。你可以将这些 jar 包都放到 HDFS 的一个地方给多个工作流使用。对于该工作流中的所有 Action 都可以使用到这些 jar 包。
    • 当使用上面的配置后无需另外指定 ShareLib 的位置。如果你在 job.properties 中配置了 oozie.use.system.libpath=true,那么 Oozie 将知道 ShareLib 的位置并自动将其导入进来。
  • 创建命名为 lib 的目录到 HDFS 中与 workflow.xml 文件相同的位置,然后将需要的 jar 包放到该目录中来
    • 如果这些 jar 包仅仅只有一个特定的工作流需要用到,那么这种方式比较好。同样,对于该工作流中的所有 Action 都可以使用到这些 jar 包。
  • 在 Action 中用 <archive> 标签指定单个 jar 包的路径,多个 jar 包可以配置多个 archive 标签
    • 如果你希望某些包只能够在特定的一个 Action 中使用,那么这种方式比较好。如果你需要新增或移除一些 jar 包,你必须修改你的 workflow.xml
  • 将 jar 包添加到 ShareLib(例如:/user/oozie/share/lib/lib_<timestamp>/pig)
    • 虽然这种方式也可以奏效,但是并不推荐,原因如下:
      • 这些额外的 jar 包将导入到每一个使用到这个 ShareLib 的工作流中,这可能会给这些工作流或者使用者带来不可预知的影响
      • 当更新 ShareLib 的时候,你需要重新复制这些额外的 jar 包到新的 ShareLib 中

总结

首先,这些变化看起来似乎比较复杂且无法避免。那么请记住,简而言之,我们所做的是额外多加了时间戳(lib_<timestamp> 目录)。ShareLib 的工作方式还是跟以前一样,你也无需更新任何已有的工作流。除了安装上的变化(Cloudera Manager 可以帮助你完成),其他的所有变动都不会有影响,都是为了使得事情变得简单。



原文标题:How-to: Use the ShareLib in Apache Oozie (CDH 5)

原文作者:Robert Kanter

原文链接:https://blog.cloudera.com/blog/2014/05/how-to-use-the-sharelib-in-apache-oozie-cdh-5/

如果您觉得我的文章对您有帮助,不介意您请我喝杯咖啡