- Sink API
- 将 Connecter 集成至 Table /SQL API
- Catalog API
在正式介绍这些 API 的细节之前,要把这些 API 以它们的分层列了出来,下面一层 API 是 DataStream ,针对 Java 开发一般都是基于 DataStream API 直接开发的。再往上一层就是 Table 和 SQL API ,Connector API 分层也是类似的,如果是想实现一个 Connector 的话其实是一个自底向上的过程。首先需要实现 DataStream 层上的 Source 还有 Sink API ,这个是不可或缺的。在实现了 Source、Sink 之后我们为了支持 Table 、Catalog ,需要在其上针对于 Table 层对于 Connector 提供的 API 来进行再次的开发。那接下来的介绍也会按照这个顺序,从底向上来介绍每一层 API 的基本的逻辑以及开发时需要注意的一些问题。
一、Source API
Source API 已经引入很多版本,从 1.12 开始我们有了 Source API 的第一个版本,到 Flink 1.14 开始逐渐达到一个稳定的状态,并标记成 Public。如果了解 Flink 的时间较长,我们之前还有 InputFormat 和 SourceFunction。请大家注意这些 API 在 2.0 都会被弃用掉,如果需要开发一个新的 Connector ,请关注最新的 Source API 。
从整体的设计来看,Source API 使用了主从的结构,和 Flink 的集群结构是类似的,它分为了两个部分,第一部分就是 SplitEnumerator ,它相当于整个 Source 的大脑,从名字上来看它的主要功能就是枚举、分片。
分片是 Source 对外部系统的部分抽象,比如 Kafka 一个分片就是一个 Topic 里的 Partition。如果是一个文件系统的 Source ,那一个 Split 就是一个文件或者是一个文件夹。SplitEnumerator 的工作就是在外部系统当中发现这些分片并把它做成任务分配给最终真正进行干活的,我们称为 SourceReader 。SplitEnumerator 是作业级别的,也就是每个作业或者说每个 Source 是只有一个的, SourceReader 是 Subtask 级别的,整个 Source 的并发是多少,那我们 SourceReader 的实例就有多少。SourceReader 和 Enumerator之间是通过 JM 和 TM 的 RPC 进行通信的,我们在这之上也封装了一些事件能够让 Enumerator 和 Reader 之间进行沟通,我们称之为 Source Event,这样能够更好地协调 Enumerator 和 Reader 之间的任务分配和全局管理的工作。
为了进一步简化用户对 Source 的开发过程,正如上图所示,我们提供 SourceReaderBase 的基类,SourceReader 是一个相当于比较底层的接口,为了简化开发难度,我们也提供了一个 SourceReaderBase ,它进一步把 Source 和外部系统之间的沟通部分和与 Flink 进行协作的部分做了一个拆分,这样做的好处是 Source 开发者能够更加关注和外部系统之间的交互,而不需要过多关注和 Flink 之间的 Checkpoint 处理、会不会影响 Flink 主线程的工作等问题。在 SourceReaderBase 的设计之下,我们又抽出了一个名为 SplitReader 的 API,它才是真正的从外部系统中拉取数据,根据 Enumerato