Flink1.12.3部署介绍
FLink架构和组件介绍
下面我们来介绍Flink集群的架构角色。
Flink集群的初始角色是Flink的客户端client,client持有我们编写的代码,并会将代码翻译成JobGraph并提交给JobManager
JobManager分发任务给各个TaskManager,TaskManager是实际跑任务处理数据的地方,比如从source拉去数据,做MR操作,最后输出都是在TaskManager的工作任务中。
当我们需要部署一个Flink集群时,有多个模式可选。我们首先来看看Flink内部各个组件。
- Flink 客户端
- 组件功能:
- 编译批处理或者流处理应用为工作流图(dataflow graph),然后把该工作流提交到JobManager
- 组件实现:
- Flink的命令行模式, e.g.
./bin/flink run ./examples/streaming/TopSpeedWindowing.jar
- Flink REST api, e.g.
curl -X POST /v1/jar/xxx.jar/run -d {}
- SQL客户端
- Python的交互式命令行环境,e.g.
pyflink-shell.sh local
- Scala的交互式命令行环境,e.g.
bin/start-scala-shell.sh local
- Flink的命令行模式, e.g.
- 组件功能:
- JobManager
- 组件功能:
- JobManager是Flink集群的中心协调者。JobManager的实现拥有不同的资源提供者(Resource Provider),这些不同的资源提供者拥有不同的高可用模式(High Availability),资源分配策略(resource allocation behavior)和任务提交模式(job submission mode)。下面是Flink支持的任务提交模式:
- Application Mode: 这种模式下一个Flink集群只运行一个job,job的入口方法在JobManager上运行,同时可通过调用
execute
/executeAsync
方法多次启动job. - Per-Job Mode: 运行唯一个Job. Job的入口方法在集群启动的时候就会被调用。
- Application Mode: 这种模式下一个Flink集群只运行一个job,job的入口方法在JobManager上运行,同时可通过调用
- Seesion Mode: 一个JobManager实例管理多个Job,并且集群可以启多个TaskManager.
- JobManager是Flink集群的中心协调者。JobManager的实现拥有不同的资源提供者(Resource Provider),这些不同的资源提供者拥有不同的高可用模式(High Availability),资源分配策略(resource allocation behavior)和任务提交模式(job submission mode)。下面是Flink支持的任务提交模式:
- 组件实现:
- Standalone: Standalone是Flink的标准模式,它只需要Java虚拟机运行即可部署,并且可以部署到多种调度平台上,e.g. Docker, Docker Swarm/Compose, non-native Kubernetes
- K8S
- YARN
- Mesos(2020-4-7 Mesos开启投票,把该项目移至了Apache Attic, 正式退休了)
- 组件功能:
- TaskManager
- 组件功能
- 专门用户执行Flink Job的服务
- 组件功能
- High Availability Service Provider
- 组件功能:
- JobManager可以配置成高可用的模式。也就是如果一个JobManager挂掉了,待命的JobManager能及时接管挂掉的JobManager。为了能够更快的恢复服务,可以有多个JobManager一直处于运行状态待命。
- 组件实现:
- Zookeeper
- K8S HA
- 组件功能:
- File Storage and Persistency
- 组件功能:
- Flink用于实现checkpointing所依赖的外部文件存储系统
- 组件实现:
- AmazonS3
- HDFS
- OpenStack Swift FS
- 阿里云对象存储
- Azure Blob Storage
- 组件功能:
- Resource Provider
- 组件功能:
- Flink可以通过多种不同的Resource Provider进行部署
- 组件实现:
- K8S
- YARN
- Mesos
- 组件功能:
- Metrics Storage
- 组件功能:
- Flink的内部组件,用于报告内部的各种指标和Job的运行指标。
- 组件实现
- 可以使用各种reporter对内部系统开放实时运行指标
- 组件功能:
- Application-Level data source and sink:
- 组件功能:
- 这个不是Flink的技术性组件,当我们部署在生产服务器的时候需要考虑。也就是他们通常说的各种connector
- 组件实现:
- Kafka connector
- Amazon S3
- es
- Cassandra
- 组件功能:
部署模式介绍
Flink运行我们开发的应用有三种方式:
- Application Mode
- Per-Job Mode
- Seesion Mode
上述三种模型主要不同点:
- 集群的生命周期和资源隔离保障的机制不同
- main方法入口点运行的在client还是cluster端的不同
有图为证:
Application Mode
其他所有的部署模式,其应用的main()方法都是在client端运行的。运行的过程包括下载应用的依赖到本地,执行main()方法导出Flink能执行的dataflow graph,比如JobGraph,然后把依赖和JobGraph(s)发给Flink集群。这种方式是的客户端资源消耗比较严重,因为需要大量的网络带宽去下载依赖和传送最终的二进制代码片段给FLink集群,并且需要CPU时间片来执行main()方法。如果你的client端还有其他的用户应用的话,问题将会更加凸显。
基于上述的理解,Application模式创建的只有一个job的集群,并且应用程序的main()方法在JobManager上运行。一个application模式的集群我们其实可以看做是包含一个应用程序包含了多个job的session模式的集群。通过架构图,我们可以看出application模式的资源隔离,负载均衡保障和Per-Job模式是一样的,但是它们的粒度不同。Application模式下在JobManager上运行main()方法节省CPU时间,同时也节省了带宽和时间。
注意: 在application模式下,main()方法是执行在集群上,不是像在其他模式下在client上运行。这可能对你的带有所影响,你的代码中要访问外部的某一个链接,那么jobmanager必须能访问这个链接才行,否则你的程序就会因为访问不到这个链接而产生问题。
对比Per-Job的模式,application模式允许提交的应用程序包含多个Job。Job的顺序不会受到不同的部署方式的影响,但是会受到execute()是什么时候调用的影响。我们程序中使用execute()开启多个Job的时候,会建立一个类似于同步队列的Job队列,也就是说只有当前一个job执行完成以后,后面的job才会开始执行。而使用executeAsync()开启多个Job,会简历一个异步的Job队列。
注意:Application模式上运行一个包含多个Job的应用程序时,HA是不支持这种部署的情况的。application模式下的HA只支持这个应用程序中只有一个Job.
Per-Job Mode
为了提供更好的资源隔离机制,Per-Job模式使用常用的资源调度框架(e.g. YARN,k8s)来为一个Job创建一个集群。这个集群只为这一个Job而生。当这个Job执行完毕,集群也随之而关闭,其他中间产生或缓存的文件将会被清理。这种资源隔离机制更好,因为当Job发生错误时只会使自己集群的taskmanager挂掉。此外,它还能将工作负载分散到多个JobManager上,因为整个集群就只有一个Job. 综上所述,Per-Job模式是很多生产服务器喜欢采用的的模式。
Session Mode
Session模式会在运行Job之前部署好一个集群,预留或者叫提前占用一定比列的资源来接受任意提交的应用程序。所有的应用程序都运行在一个集群上。这种模式的优点就是你不需要为每个Job准备一个集群所需要的资源开销。但是,其中一个Job的错误就可能导致整个TaskManager挂掉,然后所有运行在这个taskmanager上的Job都会受到影响而失败。除此之外,当整个TaskManager挂掉了以后,在这个TaskManager上的所有失败的Job将会做恢复,这种大规模的恢复过程中,所有的Job都会去访问文件系统来获取之前的checkpoint文件,在这个过程中多个Job所对应的service是处于中段状态的。还有就是一个Flink seesion集群跑多个应用程序的这种模式将会对仅有的一个JobManager产生更多的工作负载。
小结
在Session Mode中, 集群的生命周期是独立于所有的任务之外的,集群的资源是所有的任务共享的。而在Per-Job Mode中, 每个提交的Job都会单独创建一个集群,这样会有更好的资源隔离保障,job之间不会共享集群资源,所以Per-Job集群的生命周期是和Job绑定在一起的。最后是application mode,它为每一个应用(可能包含多个Job)创建一个session集群,并在JobManager上执行main()入口方法。