在集群启动时在 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()