Flink Day01 flink简介
一、Flink简介
Apache Flink 是一个框架和分布式处理引擎,用于对无界和有界数据流进行状态计算。
官网:https://flink.apache.org/flink-applications.html
二、为什么选择Flink
- 流数据更真实地反映了我们的生活方式
- 传统的数据架构是基于有限数据集的
- 我们的目标
- 低延迟
- 高吞吐
- 结果的准确性和良好的容错性
三、flink的应用场景
- 电商和市场营销
- 数据报表、广告投放、业务流程需要
- 物联网
- 传感器实时数据采集和显示、实时报警。交通运输业
- 电信业
- 基站流量调配
- 银行和金融业
- 实时结算和通知推送,实时监测异常行为
四、 什么是有状态的流式处理
4.1 事务处理

4.2 分析处理
将数据从业务数据库复制到数仓,在进行分析和查询

4.3 有状态的流式处理

批处理: 正确性有保证,赞一批数据进行处理,可以将乱序数据等过来后在处理,缺点就是延迟高。
流处理:延迟低、速度快,缺点就是无法操作乱序数据,
第一代流处理系统:Storm
4.4 lambda结构
用两套系统,同时保证低延迟和结果准确。

第二代流处理系统: spark Streaming - 微批处理,延迟较高
4.4 flink的优点

五、Flink的主要特点
5.1 事件驱动(Event-driven)

5.2 基于流的世界观
在Flink的世界观中,一切都是由流组成的,离线数据是有界的流;实时数据是一个没有界限的流;这就是所谓的有界流和无界流

5.3 flink组件

5.4 分层API

-
最低级别的抽象只是提供有状态的流。它通过
Process Function嵌入到DataStream api中。它允许用户从一个或多个流自由处理事件, 并使用一致的容错状态。此外, 用户还可以注册事件时间和处理时间回调, 从而允许程序实现复杂的计算。 -
实际上, 大多数应用程序不需要上述的低级抽象, 而是针对核心 api进行编程, 如datastream api (有界流) 和dataset api (有界数据集)。这些流畅的 api 为数据处理提供了通用的构建块, 如各种形式的用户指定的转换、联接、聚合、窗口、状态等。在这些 api 中处理的数据类型在各自的编程语言中表示为类。
The low level Process Function与datastream api集成, 因此只能对某些操作进行较低级别的抽象。Dataset api在有界数据集上提供了其他功能, 如循环。 -
table api是以表为中心的声明性 dsl, 它可能是动态更改表 (在表示流时)。table api遵循 (扩展) 关系模型: 表附加了一个架构 (类似于关系数据库中的表), api 提供了可比较的操作, 如选择、项目、联接、分组、聚合等。table api程序以声明的方式定义了应该执行的逻辑操作,而不是准确指定操作的代码的外观。尽管table api可通过各种类型的用户定义函数进行扩展, 但它的表现力不如core api, 但使用起来更简洁 (编写的代码较少)。此外,table api程序还需要通过一个优化器, 该优化器在执行前应用优化规则。可以在
table和datastrem/dataset之间无缝转换, 从而允许程序混合table api以及datastrem/dataset api. -
flink 提供的最高级别的抽象是sql。这种抽象在语义和表达性上都类似于
table api, 但将程序表示为 sql 查询表达式。sql抽象与table api紧密交互, sql 查询可以通过table api中定义的表执行.
5.5 flink的其他特点
- 支持事件时间(event-time)和处理时间(processing-time)语义
- 精确一次(exactly-once)的状态一致性保证
- 低延迟,每秒处理数百万个事件,毫秒级延迟
- 与众多常用存储系统的连接
- 高可用,动态扩展,实现7*24小时全天候运行
六、Flink Vs Spark Streaming
流(Stream) 和 微批 (mico-batching)的区别
spark Streaming 是秒级延迟
flink 是毫秒级延迟
6.2 数据模型
- spark采用RDD模型,spark Streaming的DStream实际上也就是一组组小批数据RDD的集合
- flink基本数据模型是数据流,以及事件(Event) 序列
6.3 运行时架构
- spark是批计算,将DAG划分为不同的stage,一个完成后才可以计算下一个
- flink是标准的流执行模式,一个事件在一个节点处理完成后可以直接发往下一个节点进行处理。
6.4 作业提交的区别
https://www.jianshu.com/p/0f4725f1b7d8
七、Flink快速上手
7.1 pom.xml
- 新建java项目
- 在maven plugin中,添加scala的编译插件
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>org.czlan.flinklearning</groupId>
<artifactId>Flink_Learning</artifactId>
<version>1.0-SNAPSHOT</version>
<name>Flink_Learning</name>
<!-- FIXME change it to the project's website -->
<url>http://www.example.com</url>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
<flink.version>1.9.0</flink.version>
<scala.binary.version>2.11</scala.binary.version>
<scala.version>2.11.12</scala.version>
</properties>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.11</version>
<scope>test</scope>
</dependency>
<!-- apache flink java dependency-->
<dependency>
<groupId>org.apache.flink</groupId>
<artifactId>flink-java</artifactId>
<version>${flink.version}</version>
</dependency>
<dependency>
<groupId>org.apache.flink</groupId>
<artifactId>flink-streaming-java_${scala.binary.version}</artifactId>
<version>${flink.version}</version>
<!--<scope>provided</scope>-->
</dependency>
<!-- apache flink scala dependency-->
<dependency>
<groupId>org.apache.flink</groupId>
<artifactId>flink-scala_${scala.binary.version}</artifactId>
<version>${flink.version}</version>
<!--<scope>provided</scope>-->
</dependency>
<dependency>
<groupId>org.apache.flink</groupId>
<artifactId>flink-streaming-scala_${scala.binary.version}</artifactId>
<version>${flink.version}</version>
</dependency>
<!-- Scala Library, provided by Flink as well. -->
<dependency>
<groupId>org.scala-lang</groupId>
<artifactId>scala-library</artifactId>
<version>${scala.version}</version>
<scope>provided</scope>
</dependency>
<!--log4j依赖-->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
<version>1.7.7</version>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.17</version>
<scope>runtime</scope>
</dependency>
</dependencies>
<build>
<plugins>
<!-- Java Compiler -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.1</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
</configuration>
</plugin>
<!-- Scala Compiler -->
<plugin>
<groupId>net.alchim31.maven</groupId>
<artifactId>scala-maven-plugin</artifactId>
<version>3.4.6</version>
<executions>
<execution>
<goals>
<goal>compile</goal>
<goal>testCompile</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-assembly-plugin</artifactId>
<version>3.0.0</version>
<configuration>
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
</configuration>
<executions>
<execution>
<id>make-assembly</id>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>build-helper-maven-plugin</artifactId>
<version>1.7</version>
<executions>
<!-- Add src/main/scala to eclipse build path -->
<execution>
<id>add-source</id>
<phase>generate-sources</phase>
<goals>
<goal>add-source</goal>
</goals>
<configuration>
<sources>
<source>src/main/java</source>
<source>src/main/scala</source>
</sources>
</configuration>
</execution>
<!-- Add src/test/scala to eclipse build path -->
<execution>
<id>add-test-source</id>
<phase>generate-test-sources</phase>
<goals>
<goal>add-test-source</goal>
</goals>
<configuration>
<sources>
<source>src/test/java</source>
<source>src/test/scala</source>
</sources>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
7.2 BatchWordCount
package org.czlan.flinklearning._01_wordcount
import org.apache.flink.api.scala._
/**
* @Author:chenzhuanglan
* @Email:czlan91@live.cn
* @Date: 2020/1/23 14:59
* @Description: 批处理代码
* @Version: V1.0.0.0
*/
object BatchWordCount {
def main(args: Array[String]): Unit = {
// 创建一个批处理的执行环境
val env = ExecutionEnvironment.getExecutionEnvironment
// 从文件中读取数据
val inputPath = "/Users/chenzhuanglan/OneDrive/learning/WorkSpace/Flink_Learning/src/main/resources/hello.txt"
val inputDataSet: DataSet[String] = env.readTextFile(inputPath)
// 分词之后做count
val wordCountDataSet = inputDataSet.flatMap(_.split(" "))
// 元组,下标从0开始
.map((_, 1))
.groupBy(0)
.sum(1)
// 打印输出
wordCountDataSet.print()
}
}
7.3 StreamWordCount
需要使用nc命令(netcat命令)
nc -lk 7777
# -l 开启 监听模式,用于指定nc将处于监听模式。通常 这样代表着为一个 服务等待客户端来链接指定的端口。
# -p<通信端口> 设置本地主机使用的通信端口。有可能会关闭
# -k<通信端口>强制 nc 待命链接.当客户端从服务端断开连接后,过一段时间服务端也会停止监听。 但通过选项 -k 我们可以强制服务器保持连接并继续监听端口。
package org.czlan.flinklearning._01_wordcount
import org.apache.flink.streaming.api.scala._
/**
* @Author:chenzhuanglan
* @Email:czlan91@live.cn
* @Date: 2020/1/23 15:45
* @Description: 流处理代码
* @Version: V1.0.0.0
*/
object StreamWrodCount {
def main(args: Array[String]): Unit = {
// 创建一个流处理的执行环境
val env = StreamExecutionEnvironment.getExecutionEnvironment
// 接收socket数据流
val textDataStream = env.socketTextStream("localhost", 7777)
// 逐一读取数据,打散之后进行wordcount
val wrodCountDataStream = textDataStream.flatMap(_.split("\\s"))
.filter(_.nonEmpty)
.map((_, 1))
.keyBy(0)
.sum(1)
// 打印输出
wrodCountDataStream.print()
// 启动流式处理程序
env.execute("stream word count job")
}
}
输出结果:
SLF4J: Failed to load class "org.slf4j.impl.StaticLoggerBinder".
SLF4J: Defaulting to no-operation (NOP) logger implementation
SLF4J: See http://www.slf4j.org/codes.html#StaticLoggerBinder for further details.
3> (hello,1)
2> (sss,1)
6> (cac,1)
2> (java,1)
3> (ttil,1)
7> (ttl,1)
# 3> 中 3表示 线程编号,另外,同一个字符都会在同一个线程上执行。
# 默认的并行度是电脑的cpu核心数
八、FLink的部署
官网:https://flink.apache.org
根据本地的hadoop版本下载对应的flink版本
分为多种模式,我们主要说一下standalone和yarn,如果有时间也介绍一个docker
8.1 standalone模式
首先flink的架构是主从模式,也就是说至少有一个主节点和一个从节点;
https://flink.apache.org/downloads.html
依赖于java jdk1.8以及sshd服务
配置文件
- 修改
conf/flink-conf.yaml配置文件:- JAVA_HOME
- jobmanager.rpc.address指向主节点
- 设置jobmanager.heap.size(堆大小)和taskmanager.heap.size定义允许 jvm 在每个节点上分配的最大主内存量,单位为MB,如果flink需要更大的内存,可以通过设置环境变量FLINK_TM_HEAP覆盖默认值
- taskmanager.numberOfTaskSlots 默认为1,表示 线程跑在slot,slot是flink中最小的资源单位,每个任务的线程都会分配到单独的slot中执行;有多少个slot就能够并行的执行多少个任务。
- parallelism.default 默认为1,实际的并行度。
- rest.port 默认为8081,仪表盘web-UI
- 修改
conf/slaves配置文件,将taskmanager添加到配置文件中,最好填写ip地址。 - 修改
conf/master配置文件,web-ui的端口和ip
主要配置项有:
- 每个工作经理 (jobmanager.heap.mb的可用内存量),
- 每个任务管理器 (taskmanager.heap.mb的可用内存量),
- 每台计算机可用的 cpu 数 (taskmanager.numberOfTaskSlots),
- 默认并行度 (parallelism.default)
- 临时目录 (taskmanager.tmp.dirs)
其中临时目录,每个worker节点必须一致,可以使用nfs共享目录,或者hdfs目录。
配置完成后启动flink即可。
需要注意是的 并行度的设置:
- 每个算子都可以设置并行度
- 配置文件的并行度 < 提交job时的并行度 < 代码中设置的并行度
- 并行度大于集群配置文件的并行度,则创建job失败。
standalone HA模式:必须使用zookeeper来进行协调;
8.2 提交任务
web-ui 的方式
命令的方式:
/bin/flink run -c MainClass -p 并行度 xxxx.jar --host localhost --port 7777
关闭job
# 列出正在运行的job
/bin/flink list
# 停止job
/bin/flink cancel ID
8.3 yarn模式
以yarn模式部署Flink时,要求Flink是有Hadoop支持的版本,Hadoop环境需要保证版本在2.2以上,并且集群中安装有HDFS服务。
启动会话
./bin/yarn-session.sh -n 4 -s 2 -jm 1024m -tm 4096m -nm test -d
# -n(--container) : TaskManager数量
# -s(--slots) : 每个TaskManager的slot数量,默认一个slot一个core,默认每个taskmanager的slot的个数为1,有时可以多一些 taskmanager,做冗余;
# -jm: jobManager 的内存(单位MB)
# -tm: 每个taskmanager的内存(单位MB)
# -nm: yarn的appName(现在 yarn的 ui的名字)
# -d: 后台执行
为每个任务管理器的处理插槽数指定 -s 。我们建议将插槽的数量设置为每台计算机的处理器数
启动会话后, 可以使用./bin/flink工具将作业提交到群集。
启动yarn-session之后,就可以通过yarn来提交flink作业
./bin/flink run -m yarn-cluster -yn 4 -yjm 1024m -ytm 4096m ./examples/batch/WordCount.jar
yarn任务提交过程
- yarn 客户端需要访问 hadoop 配置才能连接到 yar 资源管理器和 hdfs;首先查看配置文件中是否配置了
YARN_CONF_DIRHADOOP_CONF_DIRHADOOP_CONF_PATH;如果没有配置,就到$HADOOP_HOME/etc/hadoop (hadoop 2)和$HADOOP_HOME/conf ) (hadoop 1)目录中找配置文件; - 在启动 新的yarn会话时,要想resourcemanager申请资源,然后将flink的jar包和配置上传到一个container上作为共享资源。
- client会向resourcemanager 申请资源启动applicationMaster,启动container,并从共享资源下载文件;完成后启动applicationMaster;
- jobmanager和applicationMaster是在一个容器中运行的,启动成功后,AM将指导jobmanager的地址。生成一个新的配置文件用来跑taskmanager,以便连接到jobmanager
- AM开始分配container给taskmanager,然后从共享资源中,下载修改后的配置文件和jar包,flink被设置为准备接受作业;


浙公网安备 33010602011771号