概述
Flink中的数据流程序是在数据流上实现转换的常规程序(例如,过滤,更新状态,定义窗口,聚合)。数据流由(例如,消息队列、套接字流、文件)创建的。结果通过接收器返回,例如,接收器可以将数据写入文件或标准输出(例如命令行终端)。Flink程序可以在各种上下文中运行,可以独立运行,也可以嵌入到其他程序中。可以在本地的 jvm
中执行,也可以在多台机器组成的集群中执行。
什么是 DataStream
DataStream API
的名称来自用于表示Flink程序中的数据集合的特殊 DataStream
类。可以将它们视为包含重复项的不可变数据集合。这些数据可以是有界的,也可以是无界的,用于处理它们的 API
是相同的,即流批一体的概念。
在使用方面,数据流与常规Java Collection类似,但在一些关键方面有很大不同。它们是不可变的,一旦创建了它们,就不能添加或删除元素。不仅遍历其中的元素,还可以使用DataStream API
操作(也称为转换)对它们进行处理。
可以通过在Flink程序中添加源来创建初始数据流。然后,可以从中派生新的流,并通过使用map、filter等API方法将它们组合起来。
Flink常规编程规范
Flink程序是转换数据流的常规程序。每个程序都由相同的基本部分组成:
- 1,获取执行环境;
- 2.加载/创建初始数据,
- 3.指定对该数据的转换,
- 4.指定把计算结果存放在哪里,
- 5.触发程序执行
现在,将对这些步骤进行概述,有关详细信息,请参阅相应的部分。注意,Java DataStream API的所有核心类都可以在 org.apache.flink.streaming.api
中找到。
StreamExecutionEnvironment
是所有Flink程序的基础。你可以在StreamExecutionEnvironment上使用这些静态方法获得一个:
getExecutionEnvironment();
createLocalEnvironment();
createRemoteEnvironment(String host, int port, String... jarFiles);
通常,只需要使用 getExecutionEnvironment()
,因为它将根据上下文做出正确选择:如果在IDE中执行程序或作为常规Java程序,它将创建一个本地环境,将在本地机器上执行程序。如果将程序打包成一个JAR文件,并通过命令行调用它,那么Flink集群管理器将执行程序的主方法,getExecutionEnvironment()将返回一个执行环境,用于在集群上执行程序。
为了指定数据源,执行环境有几种方法可以使用各种方法从文件中读取:可以将它们作为CSV文件逐行读取,也可以使用任何其他提供的源。要将文本文件作为行序列读取,可以使用:
final StreamExecutionEnvironment env = StreamExecutionEnvironment.getExecutionEnvironment();
DataStream<String> text = env.readTextFile("file:///path/to/file");
这将提供一个数据流,然后可以在其上应用转换以创建新的派生数据流。
通过调用带有转换函数的DataStream上的方法来应用转换。例如,一个map应用如下:
DataStream<String> input = ...;
DataStream<Integer> parsed = input.map(new MapFunction<String, Integer>() {
@Override
public Integer map(String value) {
return Integer.parseInt(value);
}
});
这将原始集合中的每个String转换为Integer来创建一个新的数据流。
一旦有了包含最终结果的数据流,就可以通过创建接收器将其写入外部系统。这些只是一些创建接收器的示例方法:
writeAsText(String path);
print();
上面的步骤完成时,就需要通过调用StreamExecutionEnvironment上的execute()来触发程序执行。根据ExecutionEnvironment的类型,在自己的机器上执行,或者将程序提交到集群上执行。
execute()方法将等待作业完成,然后返回jobeexecutionresult,其中包含执行时间和累加器结果。
如果不想等待作业完成,可以通过调用StreamExecutionEnvironment上的executeAsync()来触发异步作业执行。它将返回一个JobClient,可以使用它与刚刚提交的作业进行通信。例如,下面是如何通过使用executeAsync()来实现execute()的语义。
final JobClient jobClient = env.executeAsync();
final JobExecutionResult jobExecutionResult = jobClient.getJobExecutionResult().get();
关于程序执行的最后一部分对于理解何时以及如何执行Flink操作至关重要。所有Flink程序都是惰性执行的:当程序的main方法被执行时,数据加载和转换不会直接发生。相反,每个操作都被创建并添加到数据流图中。当执行环境中的execute()调用显式触发执行时,操作才会实际执行。程序是在本地执行还是在集群上执行取决于执行环境的类型。
惰性计算可以构建复杂的程序,Flink将这些程序作为一个整体规划单元执行。
编程案例
下面是一个Flink批处理案例,代表了Flink流批处理的基本流程。
import org.apache.flink.streaming.api.environment.StreamExecutionEnvironment;
import org.apache.flink.streaming.api.datastream.DataStream;
import org.apache.flink.api.common.functions.FilterFunction;
public class Example {
public static void main(String[] args) throws Exception {
final StreamExecutionEnvironment env =
StreamExecutionEnvironment.getExecutionEnvironment();
DataStream<Person> flintstones = env.fromElements(
new Person("Fred", 35),
new Person("Wilma", 35),
new Person("Pebbles", 2));
DataStream<Person> adults = flintstones.filter(new FilterFunction<Person>() {
@Override
public boolean filter(Person person) throws Exception {
return person.age >= 18;
}
});
adults.print();
env.execute();
}
public static class Person {
public String name;
public Integer age;
public Person(String name, Integer age) {
this.name = name;
this.age = age;
}
public String toString() {
return this.name + ": age " + this.age.toString();
}
}
}
数据源
源是程序读取输入的地方。可以使用 StreamExecutionEnvironment.addSource(sourceFunction) 将源附加到程序中。Flink附带了许多预实现的源代码函数,可以通过为非并行源代码实现 SourceFunction ,或者通过实现 ParallelSourceFunction 接口或为并行源代码扩展 RichParallelSourceFunction 来编写自己的自定义源代码。
有几个预定义的流源可以从 StreamExecutionEnvironment 中访问
基于文件
- readTextFile(path) -逐行读取文本文件,即遵守TextInputFormat规范的文件,并将其作为字符串返回。
- readFile(fileInputFormat, path) -按照指定的文件输入格式读取(一次)文件。
- readFile(fileInputFormat, path, watchType, interval, pathFilter, typeInfo) -这是前两个方法在内部调用的方法。它根据给定的fileInputFormat读取路径中的文件。根据所提供的watchType,这个源可以定期(每隔毫秒)监视新数据的路径(fileprocessingmode . process_continuous),或者处理一次当前路径中的数据并退出(FileProcessingMode.PROCESS_ONCE)。使用pathFilter,用户可以进一步排除正在处理的文件。
Socket-based
socketTextStream - 从 socket
中读取,元素之间使用分隔器
Collection-based:
fromCollection(Collection) - 通过Java Java.util.Collection创建数据流,所有集合中的元素是同一种类型。
fromCollection(Iterator, Class) - 通过iterator创建数据流,通过 Class 指定返回 iterator 返回数据的类型
fromElements(T …) - Creates a data stream from the given sequence of objects. All objects must be of the same type.
fromParallelCollection(SplittableIterator, Class) - Creates a data stream from an iterator, in parallel. The class specifies the data type of the elements returned by the iterator.
fromSequence(from, to) - Generates the sequence of numbers in the given interval, in parallel.
自定义
结束
下部分在下一篇中补充。