Flink Source API
(二)DataStream API
DataStream是Flink编写流处理作业的API。我们前面说过一个完整的Flink处理程序应该包含三部分:数据源(Source)、转换操作(Transformation)、结果接收(Sink)。下面我们从这三部分来看DataStream API。
addSource & fromSource 、addSink & SinkTo
- 这两组算子区别在于:addSource和addSink需要自己实现SourceFunction或者是SinkFunction,其中读取数据的逻辑,容错等都需要自己实现;
- fromSource和SinkTo,是flink提供的简易的读取和输出的算子,建议优先使用fromSource和SinkTo,并结合flink官方文档;
(三)数据源(Source)
Flink应用程序从数据源获取要处理的数据,DataStream通过StreamExecutionEnvironment.addResource(SourceFunction)
来添加数据源。为了方便使用,Flink预提几类预定义的数据源,比如读取文件的Source、通过Sockt读取的Source、从内存中获取的Source等。
1.基于集合的预定义Source
基于集合的数据源一般是指从内存集合中直接读取要处理的数据,StreamExecutionEnvironment提供了4类预定义方法。
fromCollection
fromCollection是从给定的集合中创建DataStream,StreamExecutionEnvironment提供了4种重载方法:
- fromCollection(Collection<T> data):通过给定的集合创建DataStream。返回数据类型为集合元素类型。
- fromCollection(Collection<T> data,TypeInformation<T> typeInfo):通过给定的非空集合创建DataStream。返回数据类型为typeInfo。
- fromCollection(Iterator<T> data,Class<T> type):通过给定的迭代器创建DataStream。返回数据类型为type。
- fromCollection(Iterator<T> data,TypeInformation<T> typeInfo):通过给定的迭代器创建DataStream。返回数据类型为typeInfo。
fromParallelCollection
fromParallelCollection和fromCollection类似,但是是并行的从迭代器中创建DataStream。
- fromParallelCollection(SplittableIterator<T> data,Class<T> type)
- fromParallelCollection(SplittableIterator<T>,TypeInfomation typeInfo)
和Iterable中Spliterator类似,这是JDK1.8新增的特性,并行读取集合元素。
fromElements
fromElements从给定的对象序列中创建DataStream,StreamExecutionEnvironment提供了2种重载方法:
- fromElements(T... data):从给定对象序列中创建DataStream,返回的数据类型为该对象类型自身。
- fromElements(Class<T> type,T... data):从给定对象序列中创建DataStream,返回的数据类型type。
generateSequence
generateSequence(long from,long to)从给定间隔的数字序列中创建DataStream,比如from为1,to为10,则会生成1~10的序列。
2.基于Socket的预定义Source
我们还可以通过Socket来读取数据,通过Sockt创建的DataStream能够从Socket中无限接收字符串,字符编码采用系统默认字符集。当Socket关闭时,Source停止读取。Socket提供了5个重载方法,但是有两个方法已经标记废弃。
- socketTextStream(String hostname,int port):指定Socket主机和端口,默认数据分隔符为换行符(\n)。
- socketTextStream(String hostname,int port,String delimiter):指定Socket主机和端口,数据分隔符为delimiter。
- socketTextStream(String hostname,int port,String delimiter,long maxRetry):该重载方法能够当与Socket断开时进行重连,重连次数由maxRetry决定,时间间隔为1秒。如果为0则表示立即终止不重连,如果为负数则表示一直重试。
DataStreamSource<String> socketDS = env.socketTextStream("localhost", 7777);
3.基于文件的预定义Source
基于文件创建DataStream主要有两种方式:readTextFile和readFile。(readFileStream已废弃)。readTextFile就是简单读取文件,而readFile的使用方式比较灵活。
readTextFile
readTextFile提供了两个重载方法:
- readTextFile(String filePath):逐行读取指定文件来创建DataStream,使用系统默认字符编码读取。
- readTextFile(String filePath,String charsetName):逐行读取文件来创建DataStream,使用charsetName编码读取。
DataSource<String> lineDS = env.readTextFile("D:\\test\\test.txt");
DataStreamSource<String> lineDS = env.readTextFile("D:\\test\\test.txt");
readFile
readFile通过指定的FileInputFormat来读取用户指定路径的文件。对于指定路径文件,我们可以使用不同的处理模式来处理,FileProcessingMode.PROCESS_ONCE
模式只会处理文件数据一次,而FileProcessingMode.PROCESS_CONTINUOUSLY
会监控数据源文件是否有新数据,如果有新数据则会继续处理。
readFile(FileInputFormat<T> inputFormat, String filePath, FileProcessingMode watchType, long interval,TypeInformation typrInfo)
参数 | 说明 | 实例 |
---|---|---|
inputFormat | 创建DataStream指定的输入格式 | |
filePath | 读取的文件路径,为URI格式。既可以读取普通文件,可以读取HDFS文件 | file:///some/local/file 或hdfs://host:port/file/path |
watchType | 文件数据处理方式 | FileProcessingMode.PROCESS_ONCE或FileProcessingMode.PROCESS_CONTINUOUSLY |
interval | 在周期性监控Source的模式下(PROCESS_CONTINUOUSLY),指定每次扫描的时间间隔 | 10 |
typeInformation | 返回数据流的类型 |
readFile提供了几个便于使用的重载方法,但它们最终都是调用上面这个方法的。
- readFile(FileInputFormat<T> inputFormat,String filePath):处理方式默认使用FileProcessingMode.PROCESS_ONCE。
- readFile(FileInputFormat<T> inputFormat,String filePath,FileProcessingMode watchType,long interval):返回类型默认为inputFormat类型。
需要注意:在使用FileProcessingMode.PROCESS_CONTINUOUSLY时,当修改读取文件时,Flink会将文件整体内容重新处理,也就是打破了"exactly-once"。
4.自定义Source
除了预定义的Source外,我们还可以通过实现SourceFunction
来自定义Source,然后通过StreamExecutionEnvironment.addSource(sourceFunction)
添加进来。比如读取Kafka数据的Source:
addSource(new FlinkKafkaConsumer08<>);
Properties properties = new Properties(); properties.setProperty("bootstrap.servers", "localhost:9092"); ... DataStreamSource<String> stream = env.addSource(new FlinkKafkaConsumer<String>( "kafka-test-topic", new SimpleStringSchema(), properties ));
我们可以实现以下三个接口来自定义Source:
- SourceFunction:创建非并行数据源。
- ParallelSourceFunction:创建并行数据源。
- RichParallelSourceFunction:创建并行数据源。