Flink,Storm,Spark Streaming 三种流框架的对比分析
Author:yuemeng
Company:NetEase
Date:
2016/08/05
1.Flink 架构及特性分析
Flink 是个相当早的项目,开始于 2008 年,但只在最近才得到注意。Flink 是原生的流处理系
统,提供 high level 的 API。Flink 也提供 API 来像 Spark 一样进行批处理,但两者处理的基础
是完全不同的。Flink 把批处理当作流处理中的一种特殊情况。在 Flink 中,所有的数据都看
作流,是一种很好的抽象,因为这更接近于现实世界。
1.1 基本架构
下面我们介绍下 Flink 的基本架构,Flink 系统的架构与 Spark 类似,是一个基于 Master-Slave
风格的架构。
当 Flink 集群启动后,首先会启动一个 JobManger 和一个或多个的 TaskManager。由 Client
提交 任务给 JobManager ,JobManager 再调 度任务到 各个 TaskManager 去执 行,然后
TaskManager 将心跳和统计信息汇报给 JobManager。TaskManager 之间以流的形式进行数
据的传输。上述三者均为独立的 JVM 进程。
Client 为提交 Job 的客户端,可以是运行在任何机器上(与 JobManager 环境连通即可)。
提交 Job 后,Client 可以结束进程(Streaming 的任务),也可以不结束并等待结果返回。
JobManager 主要负责调度 Job 并协调 Task 做 checkpoint,职责上很像 Storm 的 Nimbus。
从 Client 处接收到 Job 和 JAR 包等资源后,会生成优化后的执行计划,并以 Task 的单元
调度到各个 TaskManager 去执行。
TaskManager 在启动的时候就设置好了槽位数(Slot),每个 slot 能启动一个 Task,Task 为
线程。从 JobManager 处接收需要部署的 Task,部署启动后,与自己的上游建立 Netty 连
接,接收数据并处理。
可以看到 Flink 的任务调度是多线程模型,并且不同 Job/Task 混合在一个 TaskManager 进
程中。主要组件为 JobManager,TaskManager,Client,下面简要描述这三个组件的作用。
JobManager
JobManager 是 Flink 系统的协调者,它负责接收 Flink Job,调度组成 Job 的多个 Task 的执行。
同时,JobManager 还负责收集 Job 的状态信息,并管理 Flink 集群中从节点 TaskManager。
JobManager 所负责的各项管理功能,它接收到并处理的事件主要包括:
RegisterTaskManager
在 Flink 集群启动的时候,TaskManager 会向 JobManager 注册,如果注册成功,则 JobManager
会向 TaskManager 回复消息 AcknowledgeRegistration。
SubmitJob
Flink 程序内部通过 Client 向 JobManager 提交 Flink Job,其中在消息 SubmitJob 中以 JobGraph
形式描述了 Job 的基本信息。
CancelJob
请求取消一个 Flink Job 的执行,CancelJob 消息中包含了 Job 的 ID,如果成功则返回消息
CancellationSuccess,失败则返回消息 CancellationFailure。
UpdateTaskExecutionState
TaskManager 会向 JobManager 请求更新 ExecutionGraph 中的 ExecutionVertex 的状态信息,
更新成功则返回 true。
RequestNextInputSplit
运 行 在 TaskManager 上 面 的 Task , 请 求 获 取 下 一 个 要 处 理 的 输 入 Split , 成 功 则 返 回
NextInputSplit。
JobStatusChanged
ExecutionGraph 向 JobManager 发送该消息,用来表示 Flink Job 的状态发生的变化,例如:
RUNNING、CANCELING、FINISHED 等。
TaskManager
TaskManager 也是一个 Actor,它是实际负责执行计算的 Worker,在其上执行 Flink Job 的一
组 Task。每个 TaskManager 负责管理其所在节点上的资源信息,如内存、磁盘、网络,在启
动的时候将资源的状态向 JobManager 汇报。TaskManager 端可以分成两个阶段:
注册阶段
TaskManager 会向 JobManager 注册,发送 RegisterTaskManager 消息,等待 JobManager 返回
AcknowledgeRegistration,然后 TaskManager 就可以进行初始化过程。
可操作阶段
该阶段 TaskManager 可以接收并处理与 Task 有关的消息,如 SubmitTask、CancelTask、FailTask。
如果 TaskManager 无法连接到 JobManager,这是 TaskManager 就失去了与 JobManager 的联
系,会自动进入“注册阶段”,只有完成注册才能继续处理 Task 相关的消息。
Client
当用户提交一个 Flink 程序时,会首先创建一个 Client,该 Client 首先会对用户提交的 Flink
程序进行预处理,并提交到 Flink 集群中处理,所以 Client 需要从用户提交的 Flink 程序配置
中获取 JobManager 的地址,并建立到 JobManager 的连接,将 Flink Job 提交给 JobManager。
Client 会将用户提交的 Flink 程序组装一个 JobGraph, 并且是以 JobGraph 的形式提交的。一
个 JobGraph 是一个 Flink Dataflow,它由多个 JobVertex 组成的 DAG。其中,一个 JobGraph
包含了一个 Flink 程序的如下信息:JobID、Job 名称、配置信息、一组 JobVertex 等。
1.2 基于 Yarn 层面的架构
基于 yarn 层面的架构类似 spark on yarn 模式,都是由 Client 提交 App 到 RM 上面去运行,
然后 RM 分配第一个 container 去运行 AM,然后由 AM 去负责资源的监督和管理。需要说明
的是,Flink 的 yarn 模式更加类似 spark on yarn 的 cluster 模式,在 cluster 模式中,dirver 将
作为 AM 中的一个线程去运行,在 Flink on yarn 模式也是会将 JobManager 启动在 container
里面,去做个 driver 类似的 task 调度和分配,YARN AM 与 Flink JobManager 在同一个 Container
中,这样 AM 可以知道 Flink JobManager 的地址,从而 AM 可以申请 Container 去启动 Flink
TaskManager。待 Flink 成功运行在 YARN 集群上,Flink YARN Client 就可以提交 Flink Job 到 Flink
JobManager,并进行后续的映射、调度和计算处理。
1.3 组件栈
Flink 是一个分层架构的系统,每一层所包含的组件都提供了特定的抽象,用来服务于上层
组件。
Deployment 层
该层主要涉及了 Flink 的部署模式,Flink 支持多种部署模式:本地、集群(Standalone/YARN)、
云(GCE/EC2)。Standalone 部署模式与 Spark 类似,这里,我们看一下 Flink on YARN 的部署
模式
Runtime 层
Runtime 层提供了支持 Flink 计算的全部核心实现,比如:支持分布式 Stream 处理、JobGraph
到 ExecutionGraph 的映射、调度等等,为上层 API 层提供基础服务。
API 层
API 层主要实现了面向无界 Stream 的流处理和面向 Batch 的批处理 API,其中面向流处理对
应 DataStream API,面向批处理对应 DataSet API。
Libraries 层
该层也可以称为 Flink 应用框架层,根据 API 层的划分,在 API 层之上构建的满足特定应用
的实现计算框架,也分别对应于面向流处理和面向批处理两类。面向流处理支持:CEP(复
杂事件处理)、基于 SQL-like 的操作(基于 Table 的关系操作);面向批处理支持:FlinkML(机
器学习库)、Gelly(图处理)。
从官网中我们可以看到,对于 Flink 一个最重要的设计就是 Batch 和 Streaming 共同使用同一
个处理引擎,批处理应用可以以一种特殊的流处理应用高效地运行。
这里面会有一个问题,就是 Batch 和 Streaming 是如何使用同一个处理引擎进行处理的。
1.4 Batch 和 Streaming 是如何使用同一个处理引擎。
下面将从代码的角度去解释 Batch 和 Streaming 是如何使用同一处理引擎的。首先从 Flink 测
试用例来区分两者的区别。
Batch WordCount Examples
Streaming WordCount Examples
Batch 和 Streaming 采用的不同的 ExecutionEnviroment,对于 ExecutionEnviroment 来说读到
的源数据是一个 DataSet,而 StreamExecutionEnviroment 的源数据来说则是一个 DataStream。
接着我们追踪下 Batch 的从 Optimzer 到 JobGgraph 的流程,这里如果是 Local 模式构造的是
LocalPlanExecutor,这里我们只介绍 Remote 模式,此处的 executor 为 RemotePlanExecutor
最终会调用 ClusterClient 的 run 方法将我们的应用提交上去,run 方法的第一步就是获取
jobGraph , 这 个 是 client 端 的 操 作 , client 会 将 jobGraph 提 交 给 JobManager 转 化 为
ExecutionGraph。Batch 和 streaming 不同之处就是在获取 JobGraph 上面。
如 果 我 们 初 始 化 的 FlinkPlan 是 StreamingPlan , 则 首 先 构 造 Streaming 的
StreamingJobGraphGenerator 去将 optPlan 转为 JobGraph,Batch 则直接采用另一种的转化方
式。