目录
- flink特点
- 分层API
- flink与spark对比
- Hello word 批处理
- Hello word 有界流处理
- Hello word 无界流处理
- Flink部署和启动
- 运行时架构(系统架构、作业提交流程、重要概念)
- 系统架构
- 作业提交流程
- 概况性的流程图:
- standalone会话模式
- yarn 会话模式
- yarn 单作业模式
- 重要概念
flink特点
又快又准,精准一次性。
分层API
- SQL 最高层语言
- Table API 声明式领域专用语言
- DataStream / DataSet API 核心API
- 有状态流处理 底层API
flink与spark对比
① 数据处理架构
spark基于批,flink基于流。
针对流数据处理,spark先把流转为微批数据,然后再处理;flink直接处理流数据,来一个处理一个。针对批数据处理,flink认为批数据是有界的流。
② 数据模型
spark:RDD模型,SparkStreaming的DStream实际上也是一组组小批数据RDD的集合;
flink:基本数据模型就是数据流,以及事件Event序列。
③ 运行架构
spark:是计算,将DAG划分为不同的stage,一个stage完成后,统一shuffle之后,才可以给到下一个stage做计算;
flink:是标准的流执行模式,一个事件在一个节点处理完后,可以直接发往下一个节点进行处理。
Hello word 批处理
- 创建执行环境 ExecutionEnvironment
- 从文件中读取数据 dataSet = env.readTextFile(“filename”)
- 将每行数据进行分词,转换成二元组类型:将一行文本进行分词,将每个单词转换成二元组输出;
- 按照二元组第一个位置(单词)分组
- 按照二元组第二个位置(出现数量)求和,统计出现次数总和
- 打印结果
DataSet基本已经被软弃用了,后续统一使用DataStream处理批数据和流数据。
Hello word 有界流处理
基于DataStream,有界流(文件):与上面的批处理几乎一样,不同点是:①执行环境不同,StreamExecutionEnvironment
执行环境中的数据类型都是DataStream
;②需要启动执行;③打印结果不同,这里能看到单词个数逐渐增加的过程;打印结果不同点2,前面能看到线程号,相同的单词会分发到相同的子任务中,跑在同一个线程中,所以相同的单词,前面的线程号是相同的;
- 创建执行环境 StreamExecutionEnvironment
- 从文件中读取数据 dataStream = env.readTextFile(“filename”)
- 将每行数据进行分词,转换成二元组类型:将一行文本进行分词,将每个单词转换成二元组输出;
- 按照二元组第一个位置(单词)分组
- 按照二元组第二个位置(出现数量)求和,统计出现次数总和
- 打印结果
- 启动执行
Hello word 无界流处理
基于DataStream,无界流(netcat):nc -lk 7777
在当前电脑中绑定一个端口7777,可以往这个端口发送消息。
与有界流的处理几乎完全一样,只有一点不同:就是读取流的方式,无界流是socketTextStream。
- 创建执行环境 StreamExecutionEnvironment
- 从文件中读取数据 dataStream = env.socketTextStream(“hadoop111”, 7777)(可以从参数中提取主机名和端口号)
- 将每行数据进行分词,转换成二元组类型:将一行文本进行分词,将每个单词转换成二元组输出;
- 按照二元组第一个位置(单词)分组
- 按照二元组第二个位置(出现数量)求和,统计出现次数总和
- 打印结果
- 启动执行
Flink部署和启动
Flink Client提交任务Job给JobManager,由JobManager将任务分配给TaskManager们去完成工作。
部署模式
- 会话模式:适用于单个任务执行时间短,任务较多的情景。集群启动,单个任务完成了,并不会关闭集群,减少集群反复启停带来的资源消耗。
- 单作业模式:常用,适用于单个任务执行时间长的情景。有任务提交,集群启动,该任务完成,集群关闭。
- 应用模式:将任务提交给JobManager,去做解析执行,根据一个项目启动一个集群。
独立模式、Yarn模式的会话和单作业要会一种。
K8S基于Docker镜像。
运行时架构(系统架构、作业提交流程、重要概念)
系统架构
- Flink代码运行,经过优化器和图构建器,生成数据流图,客户端把数据流图发送给JobManager。提交后,任务的执行与客户端就没有关系了,客户端只是更新计算状态和计算结果。
- JobManager拿到数据流图后,将数据流图转化为作业图,再将作业图转化为执行图,将执行图分发给TaskManager。JobManager里,有通信系统,可以和客户端、所有的TaskManager通信;还有作业调度器、检查点协调器用来做作业的调度和检查点的协调。JobManager将作业分发下去之后,所有的任务执行就与JobManager没有关系了,而是由TaskManager去做。
- TaskManager收到任务执行图后,把任务拆分开,放到Task Slot中执行,Task Slot是执行一个任务所需的最小的一块资源,在这部分资源上就可以单独的去执行一个任务。不同的TaskManager上有多个Slot,就可以并行执行多个任务。在执行任务的过程中,多个TaskManager之间也可以有数据的交换。每个TaskManager上还会有内存和IO管理器、网络管理器、通信系统。TaskManager的通信系统用于与JobManager交互,发送心跳信息,当前状态,统计指标的监控信息;JobManager可以给TaskManager发送一些部署命令、停止命令、触发检查点的命令。如:点了Cancel Job按钮后,是由客户端提交了停止命令给JobManager,JobManager转发给所有的TaskManager,取消所有的Task。
作业管理器 JobManager
JobManager是控制一个应用程序执行的主进程,是Flink集群中任务管理和调度的中心。
一个Flink集群只有一个JobManager。
包含三个核心组件:JobMaster(控制、调度作业)、ResourceManager(分配、管理资源)、Dispatcher。
- JobMaster:
最核心。JobMaster负责处理单独的作业Job,所以与Job数量一一对应,可以有多个Job,自然也可以有多个JobMaster。
作业提交时,JobMaster先接收到客户端发来的要执行的作业,一般包括:Jar包,数据流图,作业图。
JobMaster将这些东西转换成执行图,执行图中包含了所有可以并发执行的任务。
JobMaster向资源管理器发出请求,申请执行任务必要的资源。
一旦获取到了足够的资源,JobMaster就会将执行图分发到TaskManager上。
在运行过程中,JobMaster会负责所有需要中央协调的操作,如检查点的协调(定期存盘,故障恢复机制)。 - 资源管理器 ResourceManager
负责资源的分配和管理,整个Flink集群中只有一个,总管只能有一个。
因为每个任务都需要分配到一个TaskManager的Slot上去执行,所以这个Slot就是资源,需要被管理。
任务槽就是Flink集群中的资源调配单元,包含了用来计算的一组CPU和内存资源。
Slot对资源的隔离主要隔离的是内存,CPU是分时复用的,不好隔离。 - 分发器 Dispatcher
提供一个REST接口,用来提交应用,并且负责为每一个新提交的作业启动一个新的JobMaster组件。
Dispatcher也会启动一个Web UI,用来方便地展示和监控作业执行的信息。
Dispatcher在架构中不是必需的,在不同的部署模式下可能会被忽略掉。
任务管理器 TaskManager
TaskManager是Flink中的工作进程。
一个Flink集群中,一般有多个TaskManager,每个TaskManager都包含了一定数量的Slots。
插槽数量,限制了该TaskManager能够并行处理的任务数量。
启动之后,TaskManager会向资源管理器注册它的插槽,让资源管理器知道当前插槽数量和使用情况。
TaskManager收到资源管理器的指令后,就会将一个或多个插槽提供给JobMaster调用。JobMaster就可以向插槽分配任务来执行了。
执行过程中,一个TaskManager可以跟运行同一应用程序的其他TaskManager交换数据,数据流在这些运行同一应用程序的TaskManager之间传输。每个TaskManager有自己的Buffer,去做数据缓冲。
作业提交流程
概况性的流程图:
standalone会话模式
yarn 会话模式
会话模式下,先有分发器和ResourceManager,等有了任务才会有JobMaster和TaskManager。
yarn 单作业模式
单作业模式下,没有Flink集群,客户端提交任务触发构建Flink的JobManager。
重要概念
- 并行度:数据并行
(1)任务并行:任务123,1进入下一个流程了,当前流程可以读取处理2,依次往后;
(2)数据并行:同一个算子中可以同时执行任务1和任务2。每一个算子operator可以包含一个或多个子任务,这些子任务在不同的线程、不同的物理机或不同的容器中完全独立地执行。一个特定算子的子任务(subtask)的个数就是它的并行度。
(3)设置并行度优先级(控制的范围越小优先级越高):每个算子设置的并行度>环境设置的并行度>提交作业的时候命令行中设置的并行度(-p 2)>配置文件中设置的并行度 - 数据传输形式:一个程序中,不同的算子可能具有不同的并行度,算子与算子之间传输形式有两种,one-to-one(forwarding)和redistributing。
计划图合并的依据:算子之间是one-to-one的关系(就是one-to-one操作),且并行度相同,可以合并。如:source-map如果并行度相同,可以合并;keyby不是one-to-one操作。 - 执行图😊:Flink中的执行图分为4层:SteamGraph----》JobGraph----》ExecutionGraph----》物理执行图。
StreamGraph:根据代码生成的最初的图,能展示程序的拓扑结构。
JobGraph:客户端优化SteamGraph从而得到JobGraph,提交给JobManager。JobGraph是客户端提交给JobManager的数据结构。主要的优化就是能合算子链,将多个符合条件的节点链在一起作为一个节点。
ExecutionGraph:JobManager根据JobGraph生成ExecutionGraph。ExecutionGraph是JobGraph的并行化版本,是调度层最核心的数据结构。
物理执行图:JobManager根据ExecutionGraph对Job进行调度后,在各个TaskManager上部署Task后形成的图,并不是一个数据结构。
按照并行度展开,执行任务后,如何向下游传输:
4. 任务(Task)和任务槽(Task Slots)
(1)Flink中每一个TaskManager都是一个JVM进程,他可能会在独立的线程上执行一个或多个子任务。
(2)为了控制一个TaskManager最多能接收多少个task,TaskManager通过task slots来进行控制,一个TaskManager至少有一个slot。
- 任务共享slot
- (1)默认情况下,flink允许子任务共享slot。这样,一个slot可以保存作业的整个管道。
(2)当我们将资源密集型和非密集型的任务同时放到一个slot中,他们就可以自行分配资源占用的比例,从而保证最重的活,平均分配给所有的TaskManager。大家一起平分当前的任务,允许不同的算子共享一个slot。
(3)同一个算子的并行子任务一定要一字排开,最大算子的并行度,就是需要占据的slot个数。 - Slot和并行度
TaskSlot:静态概念,TaskManager具有的并发执行的能力,taskmanager.numberOfTaskSlots
并行度:动态概念,TaskManager运行程序时实际使用的并发能力,parallelism.default
设置slot共享组:默认所有算子都在一个default共享组,可以通过.slotSharingGroup(“1”)设置当前算子和之后的所有算子都在共享组1中。
三个问题:
1.怎样从Flink程序得到任务?
程序与数据流:Flink上运行的程序会被映射成逻辑数据流dataflows,每个dataflows包含了3个部分:sources
----transformations
----sinks
,类似于有向无环图DAG。大部分情况下,程序中的transformations
与dataflows算子operator往往一一对应。
2.一个流处理程序,到底包含多少个任务?
以上图为例,共source、flatmap、keyby3步操作,source 1个任务,flatmap 2个任务, keyby 2个任务,一共5个任务。
3.最终执行任务,需要占用多少Slot?
根据并行度最高的定,以上图为例,需要2个slot。最好是在运行命令中加-p 2,然后sink的并行度设置为1,这样就只产生一个文件