Oozie 的 ShareLib 内部已经发生变化,从 CDH 5.0.0 开始,以下是你需要知道的
在一年前的这篇博客,我介绍了如何在 CDH 4 中使用的 Apache Oozie ShareLib。但是 ShareLib 在 CDH 5 发生了变化,尤其是目录结构,之前提及的一些内容现在已经过时了(这些变动在 OOZIE-1619 可以看到)。
目录结构变化
在 CDH 4.x 中,ShareLib 的目录结构类似下面:
1 | /user/oozie/share/lib/distcp/*.jar |
但是在 CDH 5.x 中,目录新增了一个层级,包含了一个时间戳
1 | /user/oozie/share/lib/lib_20140311155426/distcp/*.jar |
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 | drwxr-xr-x share/lib/lib_20140403151601/distcp |
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 | $ oozie admin -shareliblist |
你也可以像这样获取每一个 ShareLibs 的 jar 列表
1 | $ oozie admin -shareliblist pig |
我之前提到的,你可以在 Oozie 正在运行的时候更新 ShareLib,通过 admin -sharelibupdate
命令
1 | $ oozie admin -sharelibupdate |
如你看到的,这会让 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 | oozie.pig_10=hdfs:///share/lib/pig/pig-0.10.1/lib/ |
需要注意的是,这是一个高级功能并且是可选配置。对于大多数使用者应该使用前面提到的 ShareLib 目录,而不是使用映射文件。
最后一点
对于如何在工作流中导入其他的 jar 包,我看到不少人对此感到困惑。借此机会,我对这方面做下说明,以下是一些在工作流中导入其他 jar 包的可选方案:
- 配置
oozie.libpath=/path/to/jars,another/path/to/jars
到job.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
- 如果你希望某些包只能够在特定的一个 Action 中使用,那么这种方式比较好。如果你需要新增或移除一些 jar 包,你必须修改你的
- 将 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/