SeaTunnel 连接器 V1 到 V2 的架构演进与探究
核心概念
整个 SeaTunnel 设计的核心是利用设计模式中的控制翻转
或者叫依赖注入
,主要概括为以下两点:
上层不依赖底层,两者都依赖抽象
流程代码与业务逻辑应该分离
对于整个数据处理过程,大致可以分为以下几个流程:输入 -> 转换 -> 输出,对于更复杂的数据处理,实质上也是这几种行为的组合:
内核原理
SeaTunnel 将数据处理的各种行为抽象成Plugin
,并使用SPI
技术进行动态注册,设计思路保证了框架的灵活扩展,在以上理论基础上,数据的转换与处理还需要做统一的抽象,譬如比较有名异构数据源同步工具DataX
,也同样对数据单条记录做了统一抽象。
在 SeaTunnel V1 架构体系中,由于背靠 Spark 和 Flink 两大分布式计算框架,框架已经为我们做好了数据源抽象的工作,Flink 的 DataStream、Spark 的 DataFrame 已经是对接入数据源的高度抽象,在此基础上我们只需要在插件中处理这些数据抽象即可,同时借助于 Flink 和 Spark 提供的 SQL 接口,还可以将每一次处理完的数据注册成表,方便用 SQL 进行处理,减少代码的开发量。
实际上 SeaTunnel 最后的目的是自动生成一个 Spark 或者一个 Flink 作业,并提交到集群中运行。
SeaTunnel 连接器 V1 API 解析
架构概览
目前在项目dev
分支下,SeaTunnel 连接器 V1 API 所在的模块如图所示:
seatunnel-api-base:基础 API 层抽象
seatunnel-api-flink:Flink 引擎 API 层抽象
seatunnel-api-spark:Spark 引擎 API 层抽象
seatunnel-api-base
在基础模块中,有以下代码:
为了更清晰的理解这些类之间的关系,笔者这里制作了一张简单的 UML 类图:
整个 API 的组成可以大体分为三部分:
插件层:提供 Source、Transform、Sink 插件定义
执行层:提供执行器和运行上下文定义
构建层:提供命令行接口定义
构建层接收命令参数构建执行器,执行器初始化上下文,上下文注册插件并启动插件,至此,整个作业开始运行。
seatunnel-api-spark
在 Spark 引擎 API 层有以下代码:
同样,笔者也整理了一张 UML 类图来表示它们之间的关系:
整个流程与 Base 模块一致,在这里笔者不过多赘述,有兴趣的读者可以自行观看源码。
seatunnel-api-flink
在 Flink 引擎 API 层有以下代码:
同样,笔者也整理了一张 UML 类图来表示它们之间的关系:
整个流程与 Base 模块一致,在这里笔者不过多赘述,有兴趣的读者可以自行观看源码。
SeaTunnel 连接器 V1 运行原理
启动器模块概览
整个项目的最外层的启动类都放在以下模块中:
跟连接器 V1 有关的模块如下:
seatunnel-core-base:V1 基础启动模块
seatunnel-core-flink:V1flink 引擎启动模块
seatunnel-core-flink-sql:V1flink-sql 引擎启动模块
seatunnel-core-spark:V1spark 引擎启动模块
执行流程
为了更好的理解 SeaTunnel V1 的启动流程,笔者在这里制作了一张简单的时序图:
程序最外层的启动由start-seatunnel-${engine}.sh
开始,用户根据将配置文件从脚本传入,脚本调用org.apache.seatunnel.core.spark.SparkStarter
或者org.apache.seatunnel.core.flink.FlinkStarter
,实际上这个类只做一个工作:将所有参数拼接成spark-submit
或者flink
命令,而后脚本接收到spark-submit
或者flink
命令并提交到集群中;提交到集群中真正执行 job 的类实际上是org.apache.seatunnel.spark.SeatunnelSpark
或是org.apache.seatunnel.flink.SeatunnelFlink
,读者如果想直接深入了解作业启动核心流程的话推荐阅读这两个类的源码。
执行原理
Spark
SparkSource 插件将异构数据源接入为 DataFrame
SparkTransform 插件将 SparkSource 接入的 DataFrame 进行转换处理
SparkSink 插件将 SparkTransform 处理好的 DataFrame 写入到目标数据源
Flink
FlinkSource 插件将异构数据源接入为 DataStream
FlinkTransform 插件将 FlinkSource 接入的 DataStream 进行转换处理
SparkSink 插件将 FlinkTransform 处理好的 DataStream 写入目标数据源
SeaTunnel 连接器 V2 API 解析
架构概览
目前在项目 dev 分支下,SeaTunnel 连接器 V2 API 所在的模块如图所示:
seatunnel-api:连接器 V2 所有的 API 定义
数据抽象
SeaTunnel 连接器 V2 API 在数据层面做了抽象,定义了自己的数据类型,这是与连接器 V1 最大的不同点,连接器 V1 使用的是引擎数据抽象的能力,但是连接器 V2 自己提供的这个异构数据源统一的能力:
在所有的 Source 连接器和 Sink 连接器中,处理的都是SeaTunnelRow
类型数据,同时 SeaTunnel 也对内设置了数据类型规范,所有通过 Source 接入进来的数据会被对应的连接器转化为SeaTunnelRow
送到下游。
API Common
在 API common 包下有以下接口的定义:
在这里由于篇幅关系只介绍比较核心的几个接口:
PluginIdentifierInterface:插件唯一标识
SeaTunnelContext:SeaTunnel 应用上下文,每个 SeaTunnel Job 包含的上下文对象,保存了当前源表的元数据
SeaTunnelPluginLifeCycle:插件声明周期
具体接口中有哪些方法读者可以自行阅读对应类的源码,在这里笔者将不过多赘述。
API Source
在 API source 包下有以下接口的定义:
在这里由于篇幅关系只介绍比较核心的几个接口:
Boundedness:标识数据有界无界,连接器 V2 设计理念基于批流一体,此接口用于区分流式作业还是批式作业
Collector:数据收集器,用于收集 Source 连接器产生的数据并推往下游
SeaTunnelSource:Source 插件基类,所有的 Source 连接器主类均继承于这个接口
SourceReader:Source 插件真正处理数据接入的接口
SourceSplit:数据分片接口,连接器 V2 支持数据并行读入,提升数据接入效率
SourceSplitEnumerator:数据分片器,此接口用于分发数据分片至对应的 SourceReader 中
API Sink
在 API sink 包下有以下接口的定义:
在这里由于篇幅关系只介绍比较核心的几个接口:
SeaTunnelSink:Sink 插件基类,所有的 Sink 连接器均继承于这个接口
SinkWriter:Sink 插件真正实现数据输出的接口
SinkCommitter:用于处理
SinkWriter#prepareCommit
返回的数据信息,包含需要提交的事务信息,连接器 V2 在 Sink 设计上提供二阶段提交的接口,从而使连接器有了实现 Exactly-Once 的可能性SinkAggregatedCommitter:用于处理
SinkWriter#prepareCommit
返回的数据信息,包含需要提交的事务信息等,用于在单节点多任务一起提交事务信息,这样可以避免提交阶段二部分失败导致状态不一致的问题(注:在实现连接器时优先实现这个接口,这样会兼容性更强)
小结
连接器 V2 在架构分层上与计算引擎进行解耦,定义了自己的元数据定义以及数据类型定义,在 API 层和计算引擎层增加了翻译层,将 SeaTunnel 自定义的数据源通过翻译层接入到引擎中,从而真正实现接口和引擎分离的目的。
SeaTunnel 连接器 V2 运行原理
启动器模块概览
整个项目的最外层的启动类都放在以下模块中:
跟连接器 V2 有关的模块如下:
seatunnel-core-starter:V2 基础启动模块
seatunnel-flink-starter:V2flink 引擎启动模块
seatunnel-spark-starter:V2spark 引擎启动模块
执行流程
为了更好的理解 SeaTunnel V2 的启动流程,笔者在这里制作了一张简单的时序图:
程序最外层的启动由start-seatunnel-${engine}-new-connector.sh
开始,用户根据将配置文件从脚本传入,脚本调用org.apache.seatunnel.core.spark.SparkStarter
或者org.apache.seatunnel.core.flink.FlinkStarter
,实际上这个类只做一个工作:将所有参数拼接成spark-submit
或者flink
命令,而后脚本接收到spark-submit
或者flink
命令并提交到集群中;提交到集群中真正执行 job 的类实际上是org.apache.seatunnel.spark.SeatunnelSpark
或是org.apache.seatunnel.flink.SeatunnelFlink
,读者如果想直接深入了解作业启动核心流程的话推荐阅读这两个类的源码,连接器 V2 和连接器 V1 的启动流程基本一致。
SeaTunnel V2 on Spark
SeaTunnel Source 连接器 V2 将异构数据源接入,生成以SeaTunnelRow
为基本单位的数据源,在翻译层实现了Spark DataSource API V2
,翻译层使得 Spark 可以接入以SeaTunnelRow
为基本单位的数据源,从而实现无缝接入 Spark 的目的。
关于Spark DataSource API V2
的详细信息,读者可以参考:https://www.databricks.com/session/apache-spark-data-source-v2,由于这篇文章的主题并不是介绍 Spark 的特性,所以笔者在这里不过多赘述。
SeaTunnel V2 on Flink
SeaTunnel Source 连接器 V2 将异构数据源接入,生成以SeaTunnelRow
为基本单位的数据源,同时在翻译层实现了Flink source function
和Flink sink function
,翻译层使得 Flink 可以接入以SeaTunnelRow
为基本单位的数据源,从而实现无缝接入 Flink 的目的。
关于Flink source Function
和Flink sink function
的详细信息,读者可以参考:https://nightlies.apache.org/flink/flink-docs-release-1.15/docs/dev/datastream/sources/#the-data-source-api,由于这篇文章的主题并不是介绍 Flink 的特性,所以笔者在这里不过多赘述。
执行原理
Source 连接器接入数据源为 SeaTunnelRow,Translation 层转换 SeaTunnelRow 数据源为各种计算引擎内部的数据源,Sink 连接器接收计算引擎内部转换好的 SeaTunnelRow 数据源并写入到目标数据源中。
V1 API vs V2 API
未来展望
目前社区正在做的事情:
连接器接入,社区计划在年底接入 80+种数据源
Web 服务化,社区目前在做 Web 服务化相关工作,用户可根据 Web 界面进行作业的管理、日志查看、上下线操作
计算引擎开发,社区目前在开发自己的计算引擎,更专注于数据同步,提升性能
未来目标:
性能优化,多维度指标监控,精确流速控制,可视化大屏监控
可视化拖拉拽快速生成数据集成任务
更多调度平台无缝接入
最终目标:成功从 Apache 孵化器毕业,成为世界一流的诞生于中国的数据集成平台工具
贡献者招募
目前社区正在蓬勃向前发展,大量feature
需要去开发实现,毕业之路道阻且艰,期待更多的有志之士参与到社区共建,欢迎热爱开源的小伙伴加入 SeaTunnel 社区,有意者可发邮件至tyrantlucifer@apache.org
或微信tyrantlucifer
联系我咨询相关事宜,让我们一起用开源点燃璀璨的程序人生。
版权声明: 本文为 InfoQ 作者【Apache SeaTunnel】的原创文章。
原文链接:【http://xie.infoq.cn/article/d732530c5c111519e5cdfd6f0】。文章转载请联系作者。
评论