4、浅谈Apache Atlas-HiveMetastoreHook源码分析

208 阅读3分钟
Hive 中 MetastoreListener 的分类

​ Metastore Listeners 是一种机制,用于在 Hive Metastore 发生元数据变更时(如表的创建、修改、删除等)触发自定义的逻辑,且无需重新编译Hive。MetaStoreListener 提供了扩展和集成外部组件的方式。根据不同的 MetaStoreListener 类型,可以在不同的阶段运行。在 Hive 中提供了如下三类:

  • MetaStorePreEventListener:在元数据变更操作实际发生之前触发,适合用于预处理和验证。
  • MetaStoreEventListener:在元数据变更操作实际发生后触发,适合用于后处理和记录。其中 Atlas 提供的 HiveMetastoreHook属于这一类型
  • MetaStoreEndFunctionListener:在 Metastore 函数调用结束时触发,适合用于记录函数调用的结果和性能监控。
Atlas-HiveMetastoreHook 的实现

​ 从 Atlas 集成 Hive MetaStoreEventListener 的配置中得知两个信息

  • hive.metastore.event.listeners:Atlas 实现的 MetastoreListener 类型为 MetaStoreEventListener。
  • org.apache.atlas.hive.hook.HiveMetastoreHook:是 Atlas 实现 MetaStoreEventListener 的入口。
<property>
<name>hive.metastore.event.listeners</name>
<value>org.apache.atlas.hive.hook.HiveMetastoreHook</value>
</property>

​ 一句话总结下上述配置的作用,Atlas 的 HiveMetastoreHook 继承了 Hive 提供的抽象类 MetaStoreEventListener 并重写了其关于元数据变更后的处理方法, HiveMetastoreHook 获取到元数据表变更事件并进行后续更新元数据操作

HiveMetastoreHook 的入口
  • Atlas 源码路径:atlas/addons/hive-bridge-shim
  • 类全名:org.apache.atlas.hive.hook.HiveMetastoreHook
  • 解释:下述源码笔者删减了非主流程的部分源码仅留下核心的代码。从源码可得知该类仅为用于 Atlas 实体注册的 MetaStoreEventListener,而并非实现处理逻辑的代码,具体处理逻辑为 atlas/addons/hive-bridge 路径下的 HiveMetastoreHookImpl。
/**
 * Hive Metastore hook to capture DDL operations for atlas entity registration.
 */
public class HiveMetastoreHook extends MetaStoreEventListener {
	// .....
    private static final String ATLAS_HIVE_METASTORE_HOOK_IMPL_CLASSNAME = "org.apache.atlas.hive.hook.HiveMetastoreHookImpl"; // 实现类

    private void initialize() {
		Class.forName(ATLAS_HIVE_METASTORE_HOOK_IMPL_CLASSNAME, true, atlasPluginClassLoader);
		atlasMetastoreHookImpl = cls.getDeclaredConstructor(Configuration.class).newInstance(config); // org.apache.atlas.hive.hook.HiveMetastoreHookImpl
    }

    @Override
    public void onCreateTable(CreateTableEvent tableEvent) throws MetaException {
		atlasMetastoreHookImpl.onCreateTable(tableEvent); // 所有变更事件都交由 HiveMetastoreHookImpl 处理
    }
	// .....
}
HiveMetastoreHook 的处理流程
  1. HiveMetastoreHookImpl:通过将所有表变更事件封装成 HiveOperationContext,然后调用内部类 HiveMetastoreHook.handleEvent() 进行处理。
  2. HiveMetastoreHook:继承 AtlasHook,handleEvent()方法 与 HiveHook 逻辑类似,通过 HiveOperationContext 获取 HiveOperation,并根据 oper 创建对应的事件,交由父类 (AtlasHook) notifyEntities 处理事件。
  3. 后续流程与 HiveHook 一致,参考 Apache Atlas-HiveHook源码分析
public class HiveMetastoreHookImpl extends MetaStoreEventListener {
    private static final Logger            LOG = LoggerFactory.getLogger(HiveMetastoreHookImpl.class);
    private        final HiveHook          hiveHook;
    private        final HiveMetastoreHook hook;

    public HiveMetastoreHookImpl(Configuration config) {
        super(config);

        this.hiveHook = new HiveHook(this.getClass().getSimpleName());
        this.hook     = new HiveMetastoreHook();
    }

    // HiveMetastoreHookImpl 源码54行
	// 将变更事件封装成 HiveOperationContext,并调用 hook.handleEvent() 处理
    public void onCreateDatabase(CreateDatabaseEvent dbEvent) {
        HiveOperationContext context = new HiveOperationContext(CREATEDATABASE, dbEvent);

        hook.handleEvent(context);
    }
	// .....

    public class HiveMetastoreHook extends AtlasHook {
        public HiveMetastoreHook() {
        }

        @Override
        public String getMessageSource() {
            return HMS_SOURCE;
        }

		// HiveMetastoreHookImpl 源码115行
        public void handleEvent(HiveOperationContext operContext) {
            ListenerEvent listenerEvent = operContext.getEvent();

            if (!listenerEvent.getStatus()) {
                return;
            }

            try {
				// 1、通过 operContext 获取到 HiveOperation
                HiveOperation        oper    = operContext.getOperation();
				// 2、将 hookContext 包装为 AtlasHiveHookContext
                AtlasHiveHookContext context = new AtlasHiveHookContext(hiveHook, oper, hiveHook.getKnownObjects(), this, listenerEvent, hiveHook.isSkipTempTables());
                BaseHiveEvent        event   = null;

				// 3、基于 oper 创建相应的 event(org.apache.atlas.hive.hook.events.BaseHiveEvent 的实现类)
                switch (oper) {
                    case CREATEDATABASE:
                        event = new CreateDatabase(context);
                        break;
					// .....
                }

                if (event != null) {
                    final UserGroupInformation ugi = SecurityUtils.getUGI() == null ? Utils.getUGI() : SecurityUtils.getUGI();
					// 4 、调用父类(AtlasHook) notifyEntities 处理 event
                    super.notifyEntities(event.getNotificationMessages(), ugi);
                }
            } catch (Throwable t) {
                LOG.error("HiveMetastoreHook.handleEvent({}): failed to process operation {}", listenerEvent, t);
            }
        }
    }
}

07-HiveMetastoreHook流程图.png

​ 一句话总结下 HiveMetastoreHook 处理流程:HiveMetastoreHook 通过继承 Hive 开放的 MetaStoreEventListener 重写表元数据变更的方法,通过 HiveOperationContext 将相应的 HiveOperation 转变为对应的事件,并调用父类 Atlas 的 notifyEntities() 方法将事件消息发送至 Kafka,Topic 为 ATLAS_HOOK

​ 下面再补充下 HiveMetastoreHook 以及其他各类的关系图

08-HiveMetastoreHook类图.png