apache-atlas-hbase-bridge-源码分析

HBase元数据采集与处理
本文介绍HBase元数据的采集与处理方法,包括使用HBaseBridge进行批量采集及利用HBaseAtlasCoprocessor进行实时变更。文章还详细解析了HBaseBridge的工作流程与源码实现。

元数据类型

Hbase元数据类型, 包括命令空间、表、列族、列

public enum HBaseDataTypes {
    // Classes
    HBASE_NAMESPACE,
    HBASE_TABLE,
    HBASE_COLUMN_FAMILY,
    HBASE_COLUMN;

    public String getName() {
        return name().toLowerCase();
    }
}

Hbase元数据采集实现
1)批量采集HBaseBridge
2)实时变更 HBaseAtlasCoprocessor
虽然定义了HBASE_COLUMN,但是实际上是没有实现的,毕竟HBASE_COLUMN是动态添加的。

执行流程

HBaseBridge 执行流程如下图所示
在这里插入图片描述

源码分析

HBaseBridge #main

public class HBaseBridge {
   
//...
    private final String        metadataNamespace;
    private final AtlasClientV2 atlasClientV2;
    private final Admin         hbaseAdmin;

    public static void main(String[] args) {
        int exitCode = EXIT_CODE_FAILED;
        AtlasClientV2 atlasClientV2  =null;

        try {
            Options options = new Options();
            options.addOption("n","namespace", true, "namespace");
            options.addOption("t", "table", true, "tablename");
            options.addOption("f", "filename", true, "filename");

            CommandLineParser parser            = new BasicParser();
            CommandLine       cmd               = parser.parse(options, args);
            String            namespaceToImport = cmd.getOptionValue("n");
            String            tableToImport     = cmd.getOptionValue("t");
            String            fileToImport      = cmd.getOptionValue("f");
            Configuration     atlasConf         = ApplicationProperties.get();
            String[]          urls              = atlasConf.getStringArray(ATLAS_ENDPOINT);

           //...

            if (!AuthenticationUtil.isKerberosAuthenticationEnabled()) {
                String[] basicAuthUsernamePassword = AuthenticationUtil.getBasicAuthenticationInput();
                atlasClientV2 = new AtlasClientV2(urls, basicAuthUsernamePassword);
            } else {
                UserGroupInformation ugi = UserGroupInformation.getCurrentUser();
                atlasClientV2 = new AtlasClientV2(ugi, ugi.getShortUserName(), urls);
            }
//...
            HBaseBridge importer = new HBaseBridge(atlasConf, atlasClientV2);
            if (StringUtils.isNotEmpty(fileToImport)) {
                File f = new File(fileToImport);
                if (f.exists() && f.canRead()) {
                    BufferedReader br   = new BufferedReader(new FileReader(f));
                    String         line = null;

                    while((line = br.readLine()) != null) {
                        String val[] = line.split(":");
                        if (ArrayUtils.isNotEmpty(val)) {
                            //...
                            importer.importHBaseEntities(namespaceToImport, tableToImport);
                        }
                    }
                    exitCode = EXIT_CODE_SUCCESS;
                } else {
                    LOG.error("Failed to read the file");
                }
            } else {
                importer.importHBaseEntities(namespaceToImport, tableToImport);
                exitCode = EXIT_CODE_SUCCESS;
            }
        } catch(ParseException e) {
           //...
        } catch(Exception e) {
            //...
        }finally {
            //...
        }
    }

HBaseBridge#importHBaseEntities

importHBaseEntities 只要负责处理namespaceToImport和tableToImport参数,然后执行相应的流程

private boolean importHBaseEntities(String namespaceToImport, String tableToImport) throws Exception {
    boolean ret = false;

    if (StringUtils.isEmpty(namespaceToImport) && StringUtils.isEmpty(tableToImport)) {
        // when both NameSpace and Table options are not present
        importNameSpaceAndTable();
        ret = true;
    } else if (StringUtils.isNotEmpty(namespaceToImport)) {
        // When Namespace option is present or both namespace and table options are present
        importNameSpaceWithTable(namespaceToImport, tableToImport);
        ret = true;
    } else  if (StringUtils.isNotEmpty(tableToImport)) {
        importTable(tableToImport);
        ret = true;
    }

    return ret;
}

导入所有的命名空间和表

namespaceToImport和tableToImport均为空,导入所有的namespace和table

private void importNameSpaceAndTable() throws Exception {

    NamespaceDescriptor[] namespaceDescriptors = hbaseAdmin.listNamespaceDescriptors();

    if (ArrayUtils.isNotEmpty(namespaceDescriptors)) {
        for (NamespaceDescriptor namespaceDescriptor : namespaceDescriptors) {
            String namespace = namespaceDescriptor.getName();
            importNameSpace(namespace);
        }
    }

    TableDescriptor[] htds = hbaseAdmin.listTables();
    if (ArrayUtils.isNotEmpty(htds)) {
        for (TableDescriptor htd : htds) {
            String tableName = htd.getTableName().getNameAsString();
            importTable(tableName);
        }
    }
}

导入指定的命名空间

namespaceToImport不为空,导入指定的namespace和namespace下的table

private void importNameSpaceWithTable(String namespaceToImport, String tableToImport) throws Exception {
    importNameSpace(namespaceToImport);

    List<TableDescriptor> hTableDescriptors = new ArrayList<>();

    if (StringUtils.isEmpty(tableToImport)) {
// 导入指定namespace
        List<NamespaceDescriptor> matchingNameSpaceDescriptors = getMatchingNameSpaces(namespaceToImport);
        if (CollectionUtils.isNotEmpty(matchingNameSpaceDescriptors)) {
            hTableDescriptors = getTableDescriptors(matchingNameSpaceDescriptors);
        }
    } else {
        tableToImport = namespaceToImport +":" + tableToImport;
        TableDescriptor[] htds = hbaseAdmin.listTables(Pattern.compile(tableToImport));
        hTableDescriptors.addAll(Arrays.asList(htds));
    }

    if (CollectionUtils.isNotEmpty(hTableDescriptors)) {
        for (TableDescriptor htd : hTableDescriptors) {
            String tblName = htd.getTableName().getNameAsString();
            importTable(tblName);
        }
    }
}

导入指定的表

tableToImport不为空,导入指定的table和table的命名空间。importTable会处理表、列族的实体,没有处理列

public void importTable(final String tableName) throws Exception {
    String            tableNameStr = null;
    TableDescriptor[] htds         = hbaseAdmin.listTables(Pattern.compile(tableName));

    if (ArrayUtils.isNotEmpty(htds)) {
        for (TableDescriptor htd : htds) {
            String tblNameWithNameSpace    = htd.getTableName().getNameWithNamespaceInclAsString();
            String tblNameWithOutNameSpace = htd.getTableName().getNameAsString();

            if (tableName.equals(tblNameWithNameSpace)) {
                tableNameStr = tblNameWithNameSpace;
            } else if (tableName.equals(tblNameWithOutNameSpace)) {
                tableNameStr = tblNameWithOutNameSpace;
            } else {
                // when wild cards are used in table name
                if (tblNameWithNameSpace != null) {
                    tableNameStr = tblNameWithNameSpace;
                } else if (tblNameWithOutNameSpace != null) {
                    tableNameStr = tblNameWithOutNameSpace;
                }
            }

            byte[]                 nsByte       = htd.getTableName().getNamespace();
            String                 nsName       = new String(nsByte);
            NamespaceDescriptor    nsDescriptor = hbaseAdmin.getNamespaceDescriptor(nsName);
            AtlasEntityWithExtInfo entity       = createOrUpdateNameSpace(nsDescriptor);
            ColumnFamilyDescriptor[]    hcdts        = htd.getColumnFamilies();
// 处理表、列族,没有处理列
            createOrUpdateTable(nsName, tableNameStr, entity.getEntity(), htd, hcdts);
        }
    } else {
        throw new AtlasHookException("No Table found for the given criteria. Table = " + tableName);
    }
}

createOrUpdateTable处理表、列族列实体,比较简单这里就不详细描述

导入命名空间

public void importNameSpace(final String nameSpace) throws Exception {
    List<NamespaceDescriptor> matchingNameSpaceDescriptors = getMatchingNameSpaces(nameSpace);

    if (CollectionUtils.isNotEmpty(matchingNameSpaceDescriptors)) {
        for (NamespaceDescriptor namespaceDescriptor : matchingNameSpaceDescriptors) {
            createOrUpdateNameSpace(namespaceDescriptor);
        }
    } else {
        throw new AtlasHookException("No NameSpace found for the given criteria. NameSpace = " + nameSpace);
    }
}

createOrUpdateNameSpace处理命名空间实体,比较简单这里就不详细描述

<think>嗯,用户遇到了一个Ant BuildException,具体是在解压HBase的tar.gz文件时出错了。首先,我需要理解这个错误的背景。用户可能是在安装或构建Apache Atlas时遇到了问题,因为错误路径提到了apache-atlas-sources-2.4.0,这应该是Atlas的源代码目录。 接下来,错误信息指出在展开/opt/module/apache-atlas-sources-2.4.0/distro/hbase/hbase-2.5.0.tar.gz时出错。可能的根本原因有几个方面。首先,文件路径是否正确?用户是否真的把hbase-2.5.0.tar.gz放在了这个目录下?如果路径不对,Ant任务自然找不到文件,导致解压失败。 然后,文件权限问题。用户是否有权限访问这个tar.gz文件?特别是如果使用sudo或者以特定用户运行构建命令,权限不足可能导致无法读取或解压文件。还有磁盘空间,解压大文件需要足够的空间,如果磁盘满了,也会失败。 另外,文件完整性也是一个考虑因素。下载的tar.gz文件可能损坏或不完整,导致解压时出错。用户需要确认文件的MD5或SHA校验和是否匹配。还有版本兼容性,Atlas 2.4.0是否真的支持HBase 2.5.0?有时候版本不匹配可能导致构建问题。 Ant构建脚本的问题也不能排除。检查build.xml中关于解压HBase的部分是否正确,是否有语法错误或配置错误。环境变量是否设置正确,比如JAVA_HOME或者ANT_HOME? 接下来,用户可能的身份是正在尝试从源码构建Apache Atlas的开发人员或系统管理员。他们可能对Ant构建工具和HBase有一定了解,但遇到具体错误时需要指导。深层需求可能是成功完成Atlas的构建,以便部署或开发环境使用。 需要分步骤引导用户检查每一个可能的原因。首先确认文件存在,权限正确,磁盘空间足够。然后检查文件完整性,版本兼容性,最后查看构建脚本和环境配置。如果用户按照步骤排查后问题依旧,可能需要更详细的日志或进一步的环境信息。</think>以下是关于该错误的详细技术解析及解决方案: --- ### **错误现象分析** ```bash An Ant BuildException has occurred: Error while expanding /opt/module/apache-atlas-sources-2.4.0/distro/hbase/hbase-2.5.0.tar.gz ``` 此错误发生在使用Apache Ant构建Apache Atlas时,具体是在解压HBase发行包的过程中失败。 --- ### **根本原因排查表** | 原因分类 | 具体表现 | 验证方法 | |----------------|----------------------------------|----------------------------------| | **文件路径错误** | 目标tar.gz文件缺失或路径不正确 | `ls -l /opt/module/apache-atlas-sources-2.4.0/distro/hbase/hbase-2.5.0.tar.gz` | | **权限不足** | 当前用户无读取/解压权限 | `stat -c "%a %U" /opt/module/apache-atlas-sources-2.4.0/distro/hbase/` | | **磁盘空间不足** | 解压目标分区剩余空间不足 | `df -h /opt/module` | | **文件损坏** | 下载的tar.gz包不完整 | `sha256sum hbase-2.5.0.tar.gz` | | **版本冲突** | Atlas源码与HBase版本不兼容 | 检查Atlas官方文档的版本矩阵 | --- ### **分步解决方案** #### **1. 验证基础环境** ```bash # 检查文件存在性 ls -lh /opt/module/apache-atlas-sources-2.4.0/distro/hbase/hbase-2.5.0.tar.gz # 验证权限(需至少644权限) sudo chmod 644 /opt/module/apache-atlas-sources-2.4.0/distro/hbase/hbase-2.5.0.tar.gz # 检查磁盘空间(建议保留至少5GB) df -h /opt/module ``` #### **2. 修复损坏的压缩包** ```bash # 重新下载官方包(注意校验签名) wget https://archive.apache.org/dist/hbase/2.5.0/hbase-2.5.0-bin.tar.gz mv hbase-2.5.0-bin.tar.gz /opt/module/apache-atlas-sources-2.4.0/distro/hbase/hbase-2.5.0.tar.gz # 验证完整性(SHA-256示例) echo "a1b2c3d4e5...官方提供的校验值" | sha256sum -c ``` #### **3. 调整构建配置** ```xml <!-- 修改Atlas源码中的build.xml --> <target name="prepare-hbase"> <untar src="${hbase.dist.dir}/hbase-${hbase.version}.tar.gz" dest="${hbase.home}" compression="gzip" overwrite="true" <!-- 添加覆盖参数 --> /> </target> ``` #### **4. 版本兼容性处理** - Atlas 2.4.0 官方支持矩阵: | 组件 | 测试版本 | 备注 | |-----------|-------------|-----------------------| | HBase
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

风的心愿

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值