基于 Hive Connector 的 openLooKeng Connector 创建复用机制剖析
openLooKeng,Make Big Data Simplified
openLooKeng 是一款开源的高效数据虚拟化分析引擎。本期,来自光大银行的小伙伴将为我们分享一篇博客,[基于 Hive Connector 的 openLooKeng Connector 创建复用机制剖析],非常感谢这位小伙伴的投稿。
基于 Hive Connector 的 openLooKeng Connector 创建复用机制剖析
本文作者 / 程一舰 中国光大银行总行信息科技部
前言
openLooKeng 作为一种跨多源数据的联邦计算引擎,天然的支持第三方数据源 Connector 的开发。如何进行简单的 Connector 的开发这里就不具体介绍了,具体可以参考自带的 example 示例。最近由于业务需要,需要对 Hive Connector 进行改造以支持我们的场景。为了避免对社区原生 Hive Connector 的侵入,我通过复用并自定义的方式创建了一个新的 Mpp Connector。这里就以此为例,谈一谈这其中的机制。
1. 执行逻辑
上图是一个 Hive Connector 的整体执行逻辑,一条查询语句到了 openLooKeng,会通过 Coordinator 进行解析,然后通过 Thrift 接口访问 Hive 的 Metastore 获取相关的元数据信息,这其中包括有哪些数据库,每个库里有哪些表以及表的数据位置及字段等信息。拿到这些信息后就会通过调度任务去 HDFS 上的具体位置拉取数据,最后将数据返回 Coordinator 进行聚合并返回。这整个过程最重要的就是获取元数据和拉取数据两个过程。话又说远了,如何创建一个新的 Connector 并复用 Hive Connector 的功能呢?
2. Plugin 加载机制
上图是我用手画的一个大体的加载机制的加载图,可能不是特别的准确但是不妨碍说事儿。openLooKeng 引擎在编译后,我们可以看到下图这样的结构
所有的 Connector 都在 plugin 目录里,当 Presto 引擎启动后,会通过 PluginManager 来对每个 Connector 进行加载,如加载图所示。当具体进行某个 Connector 加载的时候,就会访问该 Connector 的 Plugin 实现,在这里会定义 Connector 的名字,例如 hive-hadoop2,mysql,oracle,clickhouse 等。然后,会通过调用这里的 ConnectorFactory 来进行 Connector 实例的生成。
在 openLooKeng 中,对于一个 Connector 的具体实现也做了一些规定,有些接口是必须实现的。
(具体可点此参考:源码学习(二)--presto Connector 机制)
比如 ConnectorMetadata、SplitManager 等,这些具体的实现都需要包含在 Connector 中。所以 ConnectorFactory 进行创建 Connector 实例的时候,需要把这些都包含进去。所以我们可以看到加载图中,有不同颜色的 Module,这些不同颜色的 Module 就是根据主题来划分的一些接口的实现。
Module 是 Google 提供的一种注入框架 Guice 的一个接口,在这里面你可以对接口和实现类进行绑定(关联),比如接口 ConnectorMetadata,你具体的实现类为 HiveConnectorMetadata,在这里你可以通过 binder.bind(ConnectorMetadata.class).to(HiveConnectorMetadata.calss).in(Scopes.SINGLETON)来进行描述。
3.自定义 Connector
其实通过上面的描述,我们大概已经看到了几个关键的接口(或类)了:Plugin/ConnectorFactory/Module,那接下来我们看下如何创建一个新的 Connector 并实现复用。
(1)创建新模块
首先,我们先创建一个新的模块,起名为 presto-mpp,指定父类为 presto-root。然后,在 hetu-server 的 src/main/provisio/hetu.xml 中添加如下的内容,用来制定打包路径信息。
再然后,确保在父目录下的 pom.xml 中添加了模块。
有了以上,就创建好了一个新的 Connector 了,但是此时如果编译,会告诉你该实现的接口都还没实现,所以接下来我们就要实现或复用这些必须的接口。
\
(2)实现或复用接口
我们先来看一个最“究极”的复用,就是我们平时用的 Hive Connector,如果你留意了会发现,我们平时用的 Hive Connector 在配置文件里其实是这么配置的:
没错,就是 hive-hadoop2,所以其实这个 Connector 是由下图所示的 presto-hive-hadoop2 来提供的。
再继续看他的代码,只有这么一行有效内容,就是 super("hive-hadoop2"),没错,他就自己完成了一件事,定义这个 connector 的名字,那其他所有的工作是谁来做的呢?我们可以看到,他继承了 HivePlugin,所以,其他所有的工作都是靠 presto-hive 模块来完成的。
那到这里我们就恍然大悟了,我直接自定义一个,我也可以创建一个类 Hive Connector 了,比如下图,我就轻轻松松创建了一个 mpp 的 connector,实现了读取 Hive 表的所有功能。
如果到这里就结束了,那他就只是个 hive connector 而已。如果你想要自定义里面的一些逻辑该怎么办呢?比如我想重新定义里面的数据分片逻辑?那我们就要重写这个逻辑了。
下面我们以重写数据分片逻辑为例,讲一下如何添加自定义功能。
(3)自定义分片逻辑
我们先看一下 Hive 的分片逻辑实现是在哪个类里?通过功能我们也大体能搜到这个相关类,就是 HiveSplitManager.java,这个类中的 getSplits 方法就定义了如何去读取 hive 表的数据文件,有哪些 partition,需要分成多少个 split 等。加入我们想自定义分片逻辑,我们应该怎么做呢?
我们可以自己创建一个 MppSplitManager.java,一种方式是实现 ConnectorSplitManager 接口,但是为了求同存异,即复用之前 hive 已存在的功能,又添加自定义的逻辑,我们就可以继承 HiveSplitManager 这个类,然后重写 getSplits 方法。
这里我只是简单的增加了一个自定义输出,如果我们有其他的逻辑可以尽情在这里添加即可,比如你可以通过 tableName 拿到 schemaName 和 tableName,如果你检测到 tableName 是一些白名单的表,可以对这些表做一些特定的处理,等等等等。
那这样就完了么?如果这样编译完成,依然不会生效,因为引擎并没有对你写的这个类进行实例化并绑定到 MppConnector 的 ConnectorSplitManager 实现中,这是你要通过 MppModule 来绑定你的这个类的实现,这样引擎在进行 plugin 加载的时候,就会采用你的这个实现了,如下所示。
4.总结
以上我们就完成了新建一个 Connector 并复用已有 Connector 的功能。当然了,如果你想自定义 Hive Connector 的 Metadata 信息,你也可以按照相同的方法来重新实现 HiveMetadata。这样我们其实就把 Hive Connector 变成了 JDBC 系列 Connector 了,JDBC 系列的 Mysql、Oracle 等都是通过类似的方式去实现的。这一块的实现案例我放在 Gitee 上我 fork 的 openLooKeng 的 hetu-core 代码的 mppdev 分支了。
https://gitee.com/doubledue/hetu-core/tree/mppdev/
更多的内部机制,我们以后有机会继续介绍。
- END -
欢迎访问 openLooKeng 官网
openLooKeng 代码仓
版权声明: 本文为 InfoQ 作者【openLooKeng】的原创文章。
原文链接:【http://xie.infoq.cn/article/a3186d041cf14858133ddf0d9】。文章转载请联系作者。
评论