目录
首先我们来看看flink的部署模式:
local模式,方便我们在windows环境直接运行flink代码
standalone模式:使用flink自带的集群,包括Jobmanager和TaskManager
flink on yarn模式:使用yarn作为资源调度系统,是最适合生产环境的模式
cloud云模式:像阿里云里面就有已经部署好的filnk,还有其他亚马逊云,华为云等云平台也可以部署
首先我来把上次的wordcount代码打包上传到集群运行
import org.apache.flink.streaming.api.scala._
object WordCount {
def main(args: Array[String]): Unit = {
//创建环境
val env = StreamExecutionEnvironment.getExecutionEnvironment
//设置并行度为2,standalone模式就别添加了
env.setParallelism(2)
val lineDS: DataStream[String] = env.socketTextStream("doker",8888)
val wordDS: DataStream[String] = lineDS.flatMap(_.split(","))
val kvDS: DataStream[(String, Int)] = wordDS.map((_,1))
val keyByDS: KeyedStream[(String, Int), String] = kvDS.keyBy(_._1)
val countDS = keyByDS.reduce((x, y) => (x._1, x._2 + y._2))
countDS.print()
env.execute()
}
}
standalone模式
首先来看一看flink的独立集群(standalone)
启动命令 start-cluster.sh
启动之后就会出现这两个进程,前往网页8081访问
上传jar包,指定类名,就可以提交任务,自己的虚拟机就别指定并行度了,不然任务跑不动,默认并行度是 在flink的 conf的配置文件flink-conf.yaml中parallelism.default 这个参数、
我在代码中指定了并行度为2,结果最终有5个task,slot数量不够,所以一直显示在申请资源,在把代码中并行度设置删除掉后,打包再次上传运行,最终是3个task,可以正常运行
也可以通过命令行提交
flink run -c 类名 包名 :
flink run -c com.zh.core.WordCount Flink-1.0-SNAPSHOT.jar
在TaskManager,我们可以查看print的打印信息,旁边的logs可以查看具体的运行日志
yarn模式
yarn也有2种提交模式,首先我们启动hadoop集群
1、session-cluster
首先我们需要启动集群,再提交作业,所有的作业共享资源,同一个jobmanager管理所有的taskmanager,这样的模式适合作业周期短,数据量不是特别大的情况
启动yarn session
yarn-session.sh -n 2 -s 2 -jm 1024m -tm 1096m -nm test -d
-n TaskManager的slot的数量
-s 每个TaskManager的数量,默认一个slot一个core
-jm JobManager的内存(MB)
-tm TaskManager的内存 (MB)
-nm yarn上的application 名称
-d 后台运行不过yarnsession可以动态申请taskManager的数量,可以不用指定前面两个参数
通常就直接执行以下命令就可以:
yarn-session.sh -jm 1024m -tm 1096m
然后就可以在页面或者命令行提交作业了,动态申请资源,像刚才设置并行度为2,结果运行不了的情况就不会出现了,因为1个slot不够执行task,就会申请再开一个slot,可以看到现在的slot数量是2了
注意在启动yarn-session模式后提交的flink任务都是在yarn-session上
2、per-job-cluster
一个job就对应了一个集群,单独向yarn申请资源,适合规模大,长时间运行的作业,就算是一个作业发生了OOM,也不会影响其他作业的执行
首先我们关闭yarn-session,可以在yarn页面查看yarn-session的进程
yarn application -kill yarn-sessino的applicationId
flink run -m yarn-cluster -yjm 1024m -ytm 1096m -c com.zh.core.WordCount Flink-1.0-SNAPSHOT.jar
-m yarn-cluster 指定为单独集群运行flink任务
-yjm 指定jobmanager的内存
-ytm 指定taskmanager的内存
flink运行时组件
JobManager:
1、控制一个应用程序执行的主进程,也就是说,每个应用程序都会被一个不同的JobManager所控制执行。
2、JobManager会先接收到要执行的应用程序,这个应用程序会包括:作业图(JobGraph)、逻辑数据流图(logical dataflow graph)和打包了所有的类、库和其它资源的JAR包。
3、JobManager 会把JobGraph转换成一个物理层面的数据流图,这个图被叫做"执行图”(ExecutionGraph),包含了所有可以并发执行的任务。
4、JobManager会向资源管理器(ResourceManager)请求执行任务必要的资源,也就是任务管理器(TaskManager)上的插槽(slot)。一旦它获取到了足够的资源,就会将执行图分发到真正运行它们的TaskManager上。而在运行过程中,JobManager会负责所有需要中央协调的操作,比如说检查点(checkpoints)的协调。
TaskManager:
1、TaskManager是Flink中的工作进程。通常在Flink中会有多个TaskManager运行,每一个
TaskManager都包含了一定数量的插槽(slots)。插槽的数量限制了TaskManager能够执行的任务数量。
2、TaskManager会向资源管理器注册它的插槽;收到资源管理器的指令后TaskManager就会将一个或者多个插槽提供给JobManager调用。JobManager就可以向插槽分配任务(tasks)来执行了。
3、执行过程中,一个TaskManager可以跟其它运行同一应用程序的TaskManager交换数据。
资源管理器(ResourceManager)
1、主要负责管理任务管理器( TaskManager)的插槽(slot) ,TaskManger插槽是Flink中定义的处理资源单元。
2、 Flink为不同的环境和资源管理工具提供了不同资源管理器,比如YARN、Mesos、K8s,以及standalone部署。
3、当JobManager申请插槽资源时,ResourceManager会将有空闲插槽的TaskManager分配给JobManager。如果ResourceManager没有足够的插槽来满足JobManager的请求,它还可以向资源提供平台发起会话,以提供启动TaskManager进程的容器。
分发器(Dispatcher):
1、可以跨作业运行,它为应用提交提供了REST接口。
2、当一个应用被提交执行时,分发器就会启动并将应用移交给一个JobManager。
3、当一个应用被提交执行时,分发器就会启动并将应用移交给一个JobManager。
.4、Dispatcher在架构中可能并不是必需的,这取决于应用提交运行的方式。
任务提交流程
这第一幅图是flink的内部资源申请的情况
第二幅图中省略了flink集群内部的资源申请情况,可以结合两张图看一看
1、客户端上传flink的jar包和配置到hdfs上(因为是在yarn上,启动一个application需要上传资源到resourcemanager的指定位置)
2、提交job到resourcemanager,资源也已经到位,开始申 请启动ApplicationMaster
ApplicationMaster里面会启动Flink的JobManager
3、ApplicationMaster向Resourcemanager申请Container启动TaskManager
任务调度原理
思考题
并行计算怎么实现?
1、首先是在代码中可以设置env 的 parallelism
2、算子也可以设置具体的并行度
并行的任务,占用多少slot?
比如我为一个map算子设置并行度为2
每一个slot占用单独的资源, 这样他就会申请2个slot,每一个task占用一个slot
3、一个流处理程序包含多少个任务
这个问题需要看代码中实际的并行度设置,学习完后面的知识后会容易想通
并行度(Parallelism)和槽位(Slot)
parallelism
一个特定算子的子任务(subtask)数量称之为并行度(parallelism)
那么一个stream的并行度,可以看作是算子中最大的并行度
TaksManager和Slot:
flink中每一个Taskmanager都是一个jvm进程,可以在独立的线程上执行一个或多个子任务
Slot将内存做了划分,每个Slot可以使用的内存相互隔离,CPU资源共享
通过调整任务槽的数量,用户可以定义子任务如何相互隔离。每个 TaskManager 有一个插槽意味着每个任务组在单独的 JVM 中运行(例如,可以在单独的容器中启动)。拥有多个插槽意味着更多的子任务共享同一个 JVM。同一 JVM 中的任务共享 TCP 连接(通过多路复用)和心跳消息。它们还可以共享数据集和数据结构,从而减少每个任务的开销。
像下面这样,每个Task单独启用一个Slot,这样算是比较土豪的做法
其实一组并行的task,可以共享同一个Slot,2个Slot就可以执行上面的任务了
默认情况下,Flink允许子任务共享Slot,即使是不同任务的子任务。一个Slot就可以保存整个作业的pipline