目录
前言
Flink
有非常灵活的分层
API
设计,其中的核心层就是
DataStream/DataSet API
。由于新版
本已经实现了流批一体,
DataSet API
将被弃用,官方推荐统一使用
DataStream API
处理流数
据和批数据。
DataStream
(数据流)本身是
Flink
中一个用来表示数据集合的类(
Class)。一个
Flink
程序,其实就是对
DataStream 的各种转换。
一个Flink程序的构成:
- 获取执行环境(execution environment)
- 读取数据源(source)
- 定义基于数据的转换操作(transformations)
- 定义计算结果的输出位置(sink)
- 触发程序执行(execute)
一、执行环境
1、创建执行环境
(1)getExecutionEnvironment
最简单的方式,就是直接调用
getExecutionEnvironment
方法。它会根据当前运行的上下文
直接得到正确的结果:如果程序是独立运行的,就返回一个本地执行环境;如果是创建了
jar
包,然后从命令行调用它并提交到集群执行,那么就返回集群的执行环境。
StreamExecutionEnvironment env =
StreamExecutionEnvironment.getExecutionEnvironment();
(2)createLocalEnvironment
这个方法返回一个本地执行环境。可以在调用时传入一个参数,指定默认的并行度;如果
不传入,则默认并行度就是本地的
CPU
核心数。
StreamExecutionEnvironment localEnv =
StreamExecutionEnvironment.createLocalEnvironment();
(3)createRemoteEnvironment
这个方法返回集群执行环境。需要在调用时指定
JobManager
的主机名和端口号,并指定
要在集群中运行的
Jar
包。
StreamExecutionEnvironment remoteEnv = StreamExecutionEnvironment
.createRemoteEnvironment(
"host", // JobManager 主机名
1234, // JobManager 进程端口号
"path/to/jarFile.jar" // 提交给 JobManager 的 JAR 包
);
2、执行模式(Execution Mode)
从 1.12.0
版本起,
Flink
实现了
API
上的流批统一。
DataStream API
新增了一个重要特
性:可以支持不同的“执行模式”(
execution mode
),通过简单的设置就可以让一段
Flink
程序
在流处理和批处理之间切换。这样一来,
DataSet API
也就没有存在的必要了。
- 流执行模式(STREAMING)
- 批执行模式(BATCH)
- 自动模式(AUTOMATIC)
(1)设置方式
- 通过命令行配置
bin/flink run -Dexecution.runtime-mode=BATCH ...
- 通过代码配置
StreamExecutionEnvironment env = StreamExecutionEnvironment.getExecutionEnvironment();
env.setRuntimeMode(RuntimeExecutionMode.BATCH);
建议 : 不要在代码中配置,而是使用命令行。这同设置并行度是类似的:在提交作业时指定参数可以更加灵活,同一段应用程序写好之后,既可以用于批处理也可以用于流处理。而在 代码中硬编码(hard code )的方式可扩展性比较差,一般都不推荐。
3、触发执行
Flink
是由事件驱动的,只有等到数据到来了才会触发真正的计算, 这也被称为“延迟执行”或“懒执行”(lazy execution
)。 所以我们需要显式地调用执行环境的 execute()
方法来触发程序执行。
execute()
方法将一直等待作业完成,然后返回一个执行结果(JobExecutionResult
)。
二、源算子(Source)
1、读取数据的算子就是源算子。
Flink
代码中通用的添加
source
的方式,是调用执行环境的
addSource()
方法:
DataStream<String> stream = env.addSource(...);
该方法传入一个对象参数,需要实现
SourceFunction
接口;返回
DataStreamSource
。这里的
DataStreamSource
类继承自
SingleOutputStreamOperator
类,又进一步继承自
DataStream
。所以 很明显,读取数据的 source
操作是一个算子,得到的是一个数据流(
DataStream
)。
POJO:一个简单的Java类,这个类没有实现/继承任何特殊的java接口或者类,不遵循任何主要java模型,约定或者框架的java对象。在理想情况下,POJO不应该有注解。方便数据的解析和序列化。
2、源算子种类
(1)从集合中读取数据
// 构建集合
ArrayList<Event> clicks = new ArrayList<>();
clicks.add(new Event("Mary","./home",1000L));
clicks.add(new Event("Bob","./cart",2000L));
DataStream<Event> stream = env.fromCollection(clicks);
// 不构建集合,直接列出元素
DataStreamSource<Event> stream2 = env.fromElements(
new Event("Mary", "./home", 1000L),
new Event("Bob", "./cart", 2000L)
);
(2)从文件读取数据
一个比较常见的方式就是读取日志文件。这也是批处理中最常见的读取方式:
DataStream<String> stream = env.readTextFile("clicks.csv");
(3)从 Socket 读取数据
DataStream<String> stream = env.socketTextStream("localhost", 7777);
(4)从 Kafka 读取数据
Kafka
和
Flink