1.2.1 架构介绍

如图1-7所示,Flink系统架构主要分为APIs & Libraries、Core和Deploy三层。其中APIs层主要实现了面向流处理对应的DataStream API,面向批处理对应的DataSet API。Libraries层也被称作Flink应用组件层,是根据API层的划分,在API层之上构建满足了特定应用领域的计算框架,分别对应了面向流处理和面向批处理两类,其中面向流处理支持CEP(复杂事件处理)、基于类似SQL的操作(基于Table的关系操作);面向批处理支持Flink ML(机器学习库)、Gelly(图处理)。运行时层提供了Flink计算的全部核心实现,例如支持分布式Stream作业执行、JobGraph到ExecutionGraph的映射和调度等,为API层提供了基础服务。Deploy层支持多种部署模式,包括本地、集群(Standalone、YARN、Kubernetes)及云部署(GCE/EC2)。

图1-7 Flink整体架构

1.编程接口

Flink提供了多种抽象的编程接口,适用于不同层级的用户。数据分析人员和偏向业务的数据开发人员可以使用Flink SQL定义流式作业。

如图1-8所示,Flink编程接口分为4层。

图1-8 Flink编程接口抽象

(1)Flink SQL

一项大数据技术如果想被用户接受和使用,除了应具有先进的架构理念之外,另一点非常重要的就是要具有非常好的易用性。我们知道虽然Pig中的操作更加灵活和高效,但是在都满足数据处理需求的前提下,数据开发者更愿意选择Hive作为大数据处理的开发工具。其中最重要的原因是,Hive能够基于SQL标准进行拓展,提出了HQL语言,这就让很多只会SQL的用户也能够快速掌握大数据处理技术。因此Hive技术很快得到普及。

对于Flink同样如此,如果想赢得更多的用户,就必须不断增强易用性。FlinkSQL基于关系型概念构建流式和离线处理应用,使用户能够更加简单地通过SQL构建Flink作业。

(2)Table API

Flink SQL解析生成逻辑执行计划和物理执行计划,然后转换为Table之间的操作,最终转换为JobGraph并运行在集群上。Table API和Spark中的DataSet/DataFrame接口类似,都提供了面向领域语言的编程接口。相比Flink SQL,Table API更加灵活,既可以在Java & Scala SDK中与DataStream和DataSet API相互转换,也能结合Flink SQL进行数据处理。

(3)DataStream & DataSet API

在早期的Flink版本中,DataSet API和DataStream API分别用于流处理和批处理场景。DataSet用于处理离线数据集,DataStream用于处理流数据集。DataFlow模型希望使用同一套流处理框架统一处理有界和无界数据,那么为什么Flink还要抽象出两套编程接口来处理有界数据集和无界数据集呢?这也是近年来Flink社区不断探讨的话题。目前Table和SQL API层面虽然已经能够做到批流一体,但这仅是在逻辑层面上的,最终还是会转换成DataSet API和DataStream API对应的作业。后期Flink社区将逐渐通过DataStream处理有界数据集和无界数据集,直到本书写作时,社区已经在1.11版本中对DataStream API中的SourceFunction接口进行了重构,使DataStream可以接入和处理有界数据集。在后期的版本中,Flink将逐步实现真正意义上的批流一体化。

(4)Stateful Processing Function接口

Stateful Processing Function接口提供了强大且灵活的编程能力,在其中可以直接操作状态数据、TimeService等服务,同时可以注册事件时间和处理时间回调定时器,使程序能够实现更加复杂的计算。使用Stateful Processing Function接口需要借助DataStream API。虽然Stateful Processing Function接口灵活度很高,但是接口使用复杂度也相对较高,且在DataStream API中已经基于Stateful Process Function接口封装了非常丰富的算子,这些算子可以直接使用,因此,除非用户需要自定义比较复杂的算子(如直接操作状态数据等),否则无须使用Stateful Processing Function接口开发Flink作业。

2.运行时执行引擎

用户使用组件栈和接口编写的Flink作业最终都会在客户端转换成JobGraph对象,然后提交到集群中运行。除了任务的提交和运行之外,运行时还包含资源管理器ResourceManager以及负责接收和执行Task的TaskManager,这些服务各司其职,相互合作。运行时提供了不同类型(有界和无界)作业的执行和调度功能,最终将任务拆解成Task执行和调度。同时,运行时兼容了不同类型的集群资源管理器,可以提供不同的部署方式,并统一管理Slot计算资源。第3章将会重点讲解运行时中各个组件的功能及组件之间如何协调。

3.物理部署层

物理部署层的主要功能是兼容不同的资源管理器,如支持集群部署模式的Hadoop YARN、Kubernetes及Standalone等。这些资源管理器能够为在Flink运行时上运行的作业提供Slot计算资源。第4章会重点介绍Flink物理部署层的实现,帮助大家了解如何将运行时运行在不同的资源管理器上并对资源管理器提供的计算资源进行有效管理。