在集群启动时在 hdfs 中添加一个通用的 HBase lib¶
https://blueprints.launchpad.net/sahara/+spec/edp-add-hbase-lib
用 Java 编写的 HBase 应用程序需要在 HBase 类路径上包含 JAR 文件。从 Oozie 启动的 Java 操作可以使用 oozie.libpath 配置值引用存储在 hdfs 中的 JAR 文件,但 hdfs 中没有标准的 HBase 目录位置与 Oozie 一起安装。
用户可以从集群节点手动构建自己的 HBase 目录,但如果 Sahara 在集群启动时提供构建目录的选项,将会更方便。
问题描述¶
用 Java 编写的 HBase 应用程序需要 Hbase 类路径。通常,Java 程序会通过以下方式运行:使用 /usr/bin/hbase 获取类路径
java -cp `hbase classpath`:MyHbaseApp.jar MyHBaseApp
从 EDP 启动的 Java 作业是 Oozie 操作,无法设置额外的类路径值。相反,Oozie 解决此问题的方案是在 hdfs 中创建一个 JAR 文件目录,然后将作业的 oozie.libpath 配置属性设置为该位置。这将使 Oozie 将目录中的所有 jar 文件提供给作业。
Sahara 当前支持在作业上设置 oozie.libpath 配置,但没有现有的 HBase JAR 集合可供引用。用户可以登录到集群节点,并使用 bash 或 Python 手动在 hdfs 中构建 HBase 目录。步骤相对简单
运行
hbase classpath命令以获取类路径作为字符串使用 : 字符分隔字符串
删除所有不以 .jar 结尾的路径
将所有剩余路径上传到 hdfs 中的指定目录
然而,Sahara 在集群创建时可以为包含 HBase 服务的集群选择性地执行此操作,这将相对简单。
请注意,Oozie 以两种不同的但相关的形式使用了共享 hdfs 目录的概念
Oozie sharelib 是 Oozie 发布和支持的预打包 JAR 集合,并通过将 oozie.use.system.libpath 配置参数设置为 True 从作业中引用。Sahara 已经为所有基于 Ooozie 的作业设置了此选项。官方 Oozie sharelib 随时间变化,Oozie 使用时间戳命名约定来支持升级、多个版本等。
创建包含 JAR 文件的 hdfs 目录并使用 oozie.libpath 配置参数从作业中引用它的能力对任何人开放。 这就是这里提出的内容。 此更改不会触及官方 Oozie sharelib。 如果 Oozie 最终将 HBase JAR 添加到系统 sharelib,我们可能不再需要此功能。
提议的变更¶
创建一个可以由任何支持在集群上安装 HBase 服务的配置插件共享的类。 此类应提供一种在集群节点上运行远程命令的方法,以
运行
hbase classpath命令以获取类路径作为字符串使用 : 字符分隔字符串
删除所有不以 .jar 结尾的路径
将所有剩余路径上传到 hdfs 中的预定目录
下面的参考部分中的代码示例显示了一种在 Python 脚本中执行此操作的方法,该脚本可以上传到节点并通过远程实用程序执行。
HBase hdfs 目录可以固定,不需要可配置。 例如,它可以是“/user/sahara-hbase-lib”或类似目录。 它应该可被运行 Hadoop 作业的集群用户读取。 EDP 引擎可以在运行时查询此类的目录位置。
可以向集群配置添加一个选项来控制此 hdfs 库的创建。 此选项的默认值应为 True。 如果配置选项为 True,并且集群配置了 HBase 服务,则应在 hdfs 服务启动并运行以及集群移动到“Active”状态之前创建 hdfs HBase 库。
作业需要设置 oozie.libpath 值以引用库。 直接设置它存在一些问题
hdfs 位置需要对最终用户已知
它向最终用户暴露了更多的“Oozie-ness”。 很多“Oozie-ness”已经泄露到 Sahara 的接口中,但没有理由增加它。
相反,我们应该使用 edp.use_hbase_lib 布尔配置参数来指定是否应使用 HBase hdfs 库。 如果此配置参数为 True,EDP 可以从上述实用程序类中检索 hdfs 位置并相应地设置 oozie.libpath。 请注意,如果由于某种原因,高级用户已经将 oozie.libpath 设置为某个值,则应将 HBase lib 的位置添加到该值(可能是一个逗号分隔的列表)。
替代方案¶
什么都不做。 让用户创建他们自己的共享库。
在 Sahara 中支持 Oozie Shell 操作。
Shell 操作是 Sahara 正在考虑的更通用的功能。 假设它们受支持,Shell 操作提供了一种从脚本启动 Java 应用程序的方式,并且可以无需 HBase hdfs 库即可直接设置类路径。
使用 Shell 操作将允许用户运行脚本。 在脚本中,用户将完全控制如何启动 Java 应用程序,并可以适当地设置类路径。
用户体验会略有不同。 不再是只需编写 Java HBase 应用程序并使用 edp.use_hbase_lib 设置为 True 即可启动它,用户必须编写一个包装器脚本并将其作为 Shell 操作启动。
数据模型影响¶
无
REST API 影响¶
无
其他最终用户影响¶
无
部署者影响¶
无
开发者影响¶
无
Sahara-image-elements impact¶
无
Sahara-dashboard / Horizon 影响¶
我们可能需要在 UI 上为 Java 操作添加一个简单的复选框选项来设置 edp.use_hbase_libpath 配置,以便用户无需手动添加它。
实现¶
负责人¶
- 主要负责人
huichun
- 其他贡献者
tmckay
工作项¶
依赖项¶
测试¶
在安装了 HBase 的集群上进行 EDP 集成测试将是对此进行很好的测试覆盖,因为它涉及集群配置。
单元测试可以验证是否正确设置了 oozie.libpath。
文档影响¶
我们需要记录如何在集群创建时启用共享库的创建,以及如何配置作业以引用它
参考资料¶
这里有一篇关于 Oozie 共享库的很好的博文。
这里有一个可以用来创建 lib 的简单脚本
#!/usr/bin/python
import sys
import os
import subprocess
def main():
subprocess.Popen("hadoop fs -mkdir %s" % sys.argv[1], shell=True).wait()
cp, stderr = subprocess.Popen("hbase classpath",
shell=True,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE).communicate()
paths = cp.split(':')
for p in paths:
if p.endswith(".jar"):
print(p)
subprocess.Popen("hadoop fs -put %s %s" % (os.path.realpath(p),
sys.argv[1]),
shell=True).wait()
if __name__ == "__main__":
main()