1. flink组件
作业管理器:jobmanager
任务管理器::taskManager
资源管理器:ResourceManager
分发器:Dispatcher
1.1 JobManager
JobManager 具有许多与协调 Flink 应用程序的分布式执行有关的职责:它决定何时调度下一个 task(或一组 task)、对完成的 task 或执行失败做出反应、协调 checkpoint、并且协调从失败中恢复等等。这个进程由三个不同的组件组成
1.1.1 ResourceManager
ResourceManager 负责 Flink 集群中的资源提供、回收、分配 - 它管理 task slots,这是 Flink 集群中资源调度的单位(请参考TaskManagers)。Flink 为不同的环境和资源提供者(例如 YARN、Kubernetes 和 standalone 部署)实现了对应的 ResourceManager。在 standalone 设置中,ResourceManager 只能分配可用 TaskManager 的 slots,而不能自行启动新的 TaskManager
1.1.2 Dispatcher
Dispatcher 提供了一个 REST 接口,用来提交 Flink 应用程序执行,并为每个提交的作业启动一个新的 JobMaster。它还运行 Flink WebUI 用来提供作业执行信息。
1.1.3 JobMaster
JobMaster 负责管理单个JobGraph的执行。Flink 集群中可以同时运行多个作业,每个作业都有自己的 JobMaster
1.2 TaskManagers
TaskManager(也称为 worker)执行作业流的 task,并且缓存和交换数据流。
必须始终至少有一个 TaskManager。在 TaskManager 中资源调度的最小单位是 task slot。TaskManager 中 task slot 的数量表示并发处理 task 的数量。请注意一个 task slot 中可以执行多个算子(请参考Tasks 和算子链)
2. flink任务提交流程
1:客户端提交任务到Dispatcher
2:Dispatcher启动并提交任务到JobManager
3:JobManager回去ResourceManager求对应的环境执行资源slots
4:ResourceManager启动TaskManager
5:TaskManager会把自己的slots注册到ResourceManager
6:ResourceManager发出使用slot的指令
7:由TaskManager提供slot来为JobManager提交任务提供资源
8:jobManager提交任务到slot中去执行
9:任务执行完毕,收集执行结果
3. fink集群剖析
Client 不是运行时和程序执行的一部分,而是用于准备数据流并将其发送给 JobManager。之后,客户端可以断开连接(分离模式),或保持连接来接收进程报告(附加模式)。客户端可以作为触发执行 Java/Scala 程序的一部分运行,也可以在命令行进程./bin/flink run ...
中运行
可以通过多种方式启动 JobManager 和 TaskManager:直接在机器上作为standalone 集群启动、在容器中启动、或者通过YARN等资源框架管理并启动。TaskManager 连接到 JobManagers,宣布自己可用,并被分配工作
4. flink API介绍
flink 提供了不同的抽象级别以开发流式或批处理应用程序
4.1 Stateful Stream Processing
Flink API 最底层的抽象为有状态实时流处理。其抽象实现是 Process Function,并且 Process Function 被 Flink 框架集成到了 DataStream API 中来为我们使用。它允许用户在应用程序中自由地处理来自单流或多流的事件(数据),并提供具有全局一致性和容错保障的状态。此外,用户可以在此层抽象中注册事件时间(event time)和处理时间(processing time)回调方法,从而允许程序可以实现复杂计算
4.2 DataStream/DataSet API
Flink API 第二层抽象是 Core APIs。实际上,许多应用程序不需要使用到上述最底层抽象的 API,而是可以使用 Core APIs 进行编程:其中包含 DataStream API(应用于有界/无界数据流场景)和 DataSet API(应用于有界数据集场景)两部分。Core APIs 提供的流式 API(Fluent API)为数据处理提供了通用的模块组件,例如各种形式的用户自定义转换(transformations)、联接(joins)、聚合(aggregations)、窗口(windows)和状态(state)操作等。此层 API 中处理的数据类型在每种编程语言中都有其对应的类。
Process Function 这类底层抽象和 DataStream API 的相互集成使得用户可以选择使用更底层的抽象 API 来实现自己的需求。DataSet API 还额外提供了一些原语,比如循环/迭代(loop/iteration)操作。
4.3 Table API
Flink API 第三层抽象是 Table API。Table API 是以表(Table)为中心的声明式编程(DSL)API,例如在流式数据场景下,它可以表示一张正在动态改变的表。Table API 遵循(扩展)关系模型:即表拥有 schema(类似于关系型数据库中的 schema),并且 Table API 也提供了类似于关系模型中的操作,比如 select、project、join、group-by 和 aggregate 等。Table API 程序是以声明的方式定义应执行的逻辑操作,而不是确切地指定程序应该执行的代码。尽管 Table API 使用起来很简洁并且可以由各种类型的用户自定义函数扩展功能,但还是比 Core API 的表达能力差。此外,Table API 程序在执行之前还会使用优化器中的优化规则对用户编写的表达式进行优化。
表和 DataStream/DataSet 可以进行无缝切换,Flink 允许用户在编写应用程序时将 Table API 与 DataStream/DataSet API 混合使用
4.4 SQL
Flink API 最顶层抽象是 SQL。这层抽象在语义和程序表达式上都类似于 Table API,但是其程序实现都是 SQL 查询表达式。SQL 抽象与 Table API 抽象之间的关联是非常紧密的,并且 SQL 查询语句可以在 Table API 中定义的表上执行
5 Stream API 的执行环境
此分布式运行时取决于你的应用是否是可序列化的。它还要求所有依赖对集群中的每个节点均可用
每个 Flink 应用都需要有执行环境,在该示例中为 env
。流式应用需要用到 StreamExecutionEnvironment
。
DataStream API 将你的应用构建为一个 job graph,并附加到 StreamExecutionEnvironment
。当调用 env.execute()
时此 graph 就被打包并发送到 JobManager 上,后者对作业并行处理并将其子任务分发给 Task Manager 来执行。每个作业的并行子任务将在 task slot 中执行。
注意,如果没有调用 execute(),应用就不会运行。
//批计算环境
ExecutionEnvironment env = ExecutionEnvironment.getExecutionEnvironment();
//流处理计算环境
StreamExecutionEnvironment env = StreamExecutionEnvironment.getExecutionEnvironment();
6. Dataflows数据流图
在flink中 ,一切都是数据流,所以对于批计算来说,那只是流计算的一个特例而已
Flink Dataflows是由三部分组成,分别是:source、transformation、sink结束
source数据源会源源不断的产生数据,transformation将产生的数据进行各种业务逻辑的数据处理,最终由sink输出到外部(console、kafka、redis、DB......)
基于Flink开发的程序都能够映射成一个Dataflows
7. DataStream API简介
Flink 的 Java 和 Scala DataStream API 可以将任何可序列化的对象转化为流。Flink 自带的序列化器有
- 基本类型,即 String、Long、Integer、Boolean、Array
- 复合类型:Tuples、POJOs 和 Scala case classes
而且 Flink 会交给 Kryo 序列化其他类型。也可以将其他序列化器和 Flink 一起使用。特别是有良好支持的 Avro
7.1 source类别简介
在真实的应用中,最常用的数据源是那些支持低延迟,高吞吐并行读取以及重复(高性能和容错能力为先决条件)的数据源,例如 Apache Kafka,Kinesis 和各种文件系统。REST API 和数据库也经常用于增强流处理的能力(stream enrichment)
Flink 自带了许多预先实现的 source functions,不过你仍然可以通过实现 SourceFunction
接口编写自定义的非并行 source,也可以通过实现 ParallelSourceFunction
接口或者继承 RichParallelSourceFunction
类编写自定义的并行 sources
7.1.1 也可以直接把集合当做数据源
基于本地集合的数据源,一般用于测试场景,没有太大意义
StreamExecutionEnvironment env = StreamExecutionEnvironment.getExecutionEnvironment();
DataStreamSource<Person> dataStreamSource = env.fromCollection(Arrays.asList(
new Person(1L, "李四", 34,35.8),
new Person(2L, "王五",12, 15.4),
new Person(3L, "赵柳",33, 6.7),
new Person(4L, "外网器",12, 38.1)
));
DataStreamSource<Integer> fromElements = env.fromElements(1, 2, 3, 4);
dataStreamSource.print("person");
fromElements.print();
// 3.执行
env.execute();
7.1.2 可以直接读取hdfs数据
如果读取的是HDFS上的文件,那么需要导入Hadoop依赖
val env = StreamExecutionEnvironment.getExecutionEnvironment
val textStream = env.readTextFile("hdfs://node01:9000/flink/data")
7.1.3 可以直接从文件中读取
val env = StreamExecutionEnvironment.getExecutionEnvironment
val textStream = env.readTextFile("data/flink")
7.1.4 获取数据到流中的便捷方法是用 socket
val env = StreamExecutionEnvironment.getExecutionEnvironment
val hdfsWC = env.socketTextStream("node1",8888)
7.1.5 Kafka Source
Flink接受Kafka中的数据,首先先配置flink与kafka的连接器依赖
https://nightlies.apache.org/flink/flink-docs-release-1.9/dev/connectors/kafka.html
7.1.6 Custom Source 自定义数据源
基于SourceFunction接口实现单并行度数据源
基于ParallelSourceFunction接口实现多并行度数据源
7.2 Transformations算子简介
用户通过算子能将一个或多个 DataStream 转换成新的 DataStream,在应用程序中可以将多个数据转换算子合并成一个复杂的数据流拓扑。
这部分内容将描述 Flink DataStream API 中基本的数据转换 API,数据转换后各种数据分区方式,以及算子的链接策略
7.2.1 转换算子
map,flatMap,filter,KeyBy
5. sink
内置:redis kafaka
自定义:mysql,
本地文件: File(HDFS2.7以上)
自定义:socket