Apache Flink
Flink是构建在数据流之上的有状态计算的流计算框架,通常被人们理解为第三代大数据分析方案。
第⼀代 - Hadoop的MapReduce计算 (2006)(静态)、Storm流计算(2014.9) ;两套独⽴计算引擎,使⽤难度⼤,吞吐量小,但计算相对较快。
第⼆代 - Spark RDD 静态批处理(2014.2)、DStream|Structured Streaming 流计算;统⼀计算引擎,难度系数⼩,吞吐量大,但计算相对较慢。
第三代 - Flink DataStream(2014 .12) 流计算框架、Flink Dataset 批处理;统⼀计算引擎,难度系数不低也不⾼
可以看出Spark和Flink⼏乎同时诞⽣,但是Flink之所以发展慢,是因为早期⼈们对⼤数据的分析的认知不够深刻或者当时业务场景⼤都局限在批处理领域,从⽽导致了Flink的发展相⽐较于Spark较为缓慢,直到2016年⼈们才开始慢慢的意识流计算的重要性。
流计算领域:系统监控、舆情监控、交通预测、国家电⽹、疾病预测、银⾏/⾦融⻛控等。
更多详细分析:https://blog.csdn.net/weixin_38231448/article/details/100062961
运⾏架构
概念
Task和Operator Chain
Flink是⼀个分布式流计算引擎,该引擎将⼀个计算job拆分成若⼲个Task(等价于Spark中的Stage),每个Task都有⾃⼰的并⾏度,每个并⾏度都由⼀个线程表示,因为⼀个Task是并⾏执⾏的,因此⼀个Task底层对应⼀系列的线程,Flink称为这些线程为该Task的subtask。
与Spark不同的地⽅在于Spark是通过RDD的依赖关系实现Stage的划分⽽Flink是通过 OperatorChain 的概念实现Task的拆分。
所谓的 OperatorChain 指的是Flink在做job编织的时候,尝试将多个操作符算⼦进⾏串联到⼀个Task中,以减少数据的线程到线程传输的开销,⽬前Flink常⻅的Operatorchain的⽅式有两种:forward、hash|rebalance.
Task - 等价spark中的Stage,每个Task都有若⼲个SubTask
SubTask - 等价⼀个线程,是Task中的⼀个⼦任务
OperatorChain - 将多个算⼦归并到⼀个Task的⼀种机制,归并原则类似SparkRDD的宽窄依赖
JobManagers、TaskManagers、Clients
JobManagers - (也称为master)负责协调分布式执⾏。负责任务调度,协调检查点,协调故障恢复等,等价于Spark中的Master+Driver的功能。通常⼀个集群中⾄少有1个Active的JobManager,如果在HA模式下其他处于StandBy状态。
TaskManagers - (称为Worker) 真正负责Task执⾏计算节点,同时需要向JobManager汇报⾃身状态信息和⼯作负荷。通常⼀个集群中有若⼲个TaskManager。
client -与Spark不同,Flink中的Client并不是集群计算的⼀部分,Client仅仅负责提交任务的Dataflow Graph给JobManager,提交完成之后,可以直接退出。因此该Client并不负责任务执⾏过程中调度。
Task Slots和Resources
每⼀个Worker(TaskManager)是⼀个JVM进程,可以执⾏⼀个或者多个⼦任务(Thread/SubTask)为了控制Worker节点能够接受多个Task任务,Worker提出所谓Task slot⽤于表达⼀个计算节点的计算能⼒(每个计算节点⾄少有⼀个Task slot)。
每个TaskSlot表示的是TaskManager计算资源的固定⼦集。例如:如果⼀个TaskManager拥有3个TaskSlot,则每个Task Slot表示占⽤当前TaskManager的进程的1/3内存资源。每个Job(计算)启动的时候都拥有⾃⼰的固定的Task Slot,也就意味着避免了不同job间的在运⾏时产⽣内存资源抢占。这些被分配的Task Slot资源只能被当前job的所有Task所使⽤,不同Job的Task之间不存在资源共享和抢占问题。
但是⼀个Job会被拆分成若⼲个Task,每个Task由若⼲个SubTask构成(取决于Task并⾏度)。默认Task Slot所对应的内存资源只能在同⼀个Job下的不同Task的subtask间进⾏共享,也就意味着同⼀个Task的不同subtask不能运⾏在同⼀个Taskslot中,但是如果是相同的job的不同Task的SubTask却可以。
如果同⼀个Job的不同Task的subtask不共⽤slot,会导致资源浪费。例如下图中 source、map 操作定位为资源稀疏性操作,因为该操作占⽤内存量⼩,⽽ keyBy/windows()/apply() 涉及Shu!le会占⽤⼤量的内存资源,定位为资源密集型操作,⽐较吃内存。
因此Flink底层默认做的是不同Task的⼦任务共享Task Slot资源。因此⽤户可以将 `source/map 和keyBy/windows()/apply() 所对应的任务的并⾏度进⾏调整,将并⾏度由上图中2调整6,这样Flink底层就会做如下资源分配:
因此可以看出Flink默认⾏为是尝试将同⼀个job的下的不同Task的SubTask进⾏Task slot共享。也就意味着⼀个Job的运⾏所需要的Task Slot的个数应该等于该Job中Task并⾏度的最⼤值。当然⽤户也可以通过 程序⼲预Flink Task间Task Slot共享策略。
结论:Flink的job运⾏所需要的资源数是⾃动计算出来的,⽆需⽤户指定,⽤户只需指定计算并⾏度即可。
State Backends 状态后端
Flink是⼀个基于状态计算流计算引擎,存储的key/value状态索引的确切数据结构取决于所选的StateBackend。例如:使⽤Memory State Backend将数据存储在内存中的HashMap中,或者使⽤RocksDB(内嵌NoSQL数据,和Derby数据库类似)作为State Backend 存储状态。
除了定义保存状态的数据结构之外,State Backend 还实现逻辑以获key/value状态的时间点快照并将该快照存储为Checkpoint的⼀部分。
Savepoints
⽤Data Stream API编写的程序可以从Savepoint恢复执⾏。Savepoint允许更新程序和Flink群集,⽽不会丢失任何状态。
Savepoint是⼿动触发的Checkpoint,Savepoint为程序创建快照并将其写到State Backend。Savepoint依靠常规的Checkpoint机制。所谓的Checkpoint指的是程序在执⾏期间,程序会定期在⼯作节点上快照并产⽣Checkpoint。为了进⾏恢复,仅需要获取最后⼀次完成的Checkpoint即可,并且可以在新的Checkpoint完成后⽴即安全地丢弃较旧的Checkpoint。
Savepoint与这些定期Checkpoint类似,Savepoint由⽤户触发并且更新的Checkpoint完成时不会⾃动过期。⽤户可以使⽤命令⾏或通过REST API取消作业时创建Savepoint
环境安装
前提条件
JDK必须是1.8+,完成JAVA_HOME配置
安装Hadoop、并保证HADOOP正常运⾏(SSH免密码、HADOOP_HOME)
Flink 安装(Standalone)
上传并解压
[root@CentOS ~]# tar -zxf flink-1.10.0-bin-scala_2.11.tgz -C /usr/
[root@CentOS flink-1.10.0]# tree -L 1 ./
./
!"" bin #执⾏脚本⽬录
!"" conf #配置⽬录
!"" examples #案例jar
!"" lib # 依赖的jars
!"" LICENSE
!"" licenses
!"" log # 运⾏⽇志
!"" NOTICE
!"" opt # 第三⽅备⽤插件包
!"" plugins
#"" README.txt
8 directories, 3 files
配置flink-conf.yaml
[root@CentOS flink-1.10.0]# vi conf/flink-conf.yaml
#==============================================================================
# Common
#==============================================================================
jobmanager.rpc.address: CentOS
taskmanager.numberOfTaskSlots: 4
parallelism.default: 3
配置salves
[root@CentOS flink-1.10.0]# vi conf/slaves
CentOS
启动Flink
[root@CentOS flink-1.10.0]# ./bin/start-cluster.sh
Starting cluster.
Starting standalonesession daemon on host CentOS.
Starting taskexecutor daemon on host CentOS.
[root@CentOS flink-1.10.0]# jps
6978 NameNode
7123 DataNode
109157 StandaloneSessionClusterEntrypoint
7301 SecondaryNameNode
109495 TaskManagerRunner
109544 Jps
检查是否启动成功
⽤户可以访问Flink的 WEB UI 地址:http://centos8081
快速⼊⻔
导入依赖
<dependency>
<groupId>org.apache.hadoop</groupId>
<artifactId>hadoop-client</artifactId>
<version>2.9.2</version>
</dependency>
<dependency>
<groupId>org.apache.flink</groupId>
<artifactId>flink-streaming-scala_2.11</artifactId>
<version>1.10.0</version>
</dependency>
Client程序
import org.apache.flink.streaming.api.scala._
object FlinkWordCountQiuckStart {
def main(args: Array[String]): Unit = {
//1.创建流计算执⾏环境
val env = StreamExecutionEnvironment.getExecutionEnvironment
//2.创建DataStream - 细化
val text = env.socketTextStream("CentOS", 9999)
//3.执⾏DataStream的转换算⼦
val counts = text.flatMap(line=>line.split("\\s+"))
.map(word=>(word,1))
.keyBy(0)
.sum(1)
//4.将计算的结果在控制打印
counts.print()
//5.执⾏流计算任务
env.execute("Window Stream WordCount")
}
}
引⼊maven打包插件
<build>
<plugins>
<!--scala编译插件-->
<plugin>
<groupId>net.alchim31.maven</groupId>
<artifactId>scala-maven-plugin</artifactId>
<version>4.0.1</version>
<executions>
<execution>
<id>scala-compile-first</id>
<phase>process-resources</phase>
<goals>
<goal>add-source</goal>
<goal>compile</goal>
</goals>
</execution>
</executions>
</plugin>
<!--创建fatjar插件-->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>2.4.3</version>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>shade</goal>
</goals>
<configuration>
<filters>
<filter>
<artifact>*:*</artifact>
<excludes>
<exclude>META-INF/*.SF</exclude>
<exclude>META-INF/*.DSA</exclude>
<exclude>META-INF/*.RSA</exclude>
</excludes>
</filter>
</filters>
</configuration>
</execution>
</executions>
</plugin>
<!--编译插件-->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.2</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
<encoding>UTF-8</encoding>
</configuration>
<executions>
<execution>
<phase>compile</phase>
<goals>
<goal>compile</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
使⽤mvn package打包
使⽤WEB UI提交任务
compile
compile
使⽤mvn package打包
使⽤WEB UI提交任务
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-vtLyN2db-1583327569694)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\1583321610682.png)]