Apache Flink 使用DataStream API进行数据处理

问题导读

1.流处理和批处理分别入口是什么?
2.对于本地和远程运行程序,都可以使用哪个函数?
3.Flink数据源分为哪两类?
4.Flink DataStream和DataSet source都是基于什么格式?
5.Flink中kafka source是否为自定义?
执行环境
为了开始编写Flink程序,我们首先根据自己的需要,可以获得现有的或创建一个执行环境(executionenvironment)。 Flink支持:

  • 获取一个已经有的environment
  • 创建一个本地environment
  • 创建一个远程environment


通常,只需要使用getExecutionEnvironment()。 它会根据你的环境来选择。 如果你在IDE中的本地环境中执行,那么它将启动本地执行环境。 否则,如果正在执行JAR,则Flink集群管理器将以分布式方式执行该程序。

如果要自己创建本地或远程环境,则还可以选择使用createLocalEnvironment()和createRemoteEnvironment(String host,int port,String和.jar文件)等方法来执行此操作。
那么这个具体怎么使用,下面给大家分别给出批处理程序和流处理程序。

流处理程序:

import org.apache.flink.streaming.api.scala._
import org.apache.flink.streaming.api.windowing.time.Time

object WindowWordCount {
  def main(args: Array[String]) {

    val env = StreamExecutionEnvironment.getExecutionEnvironment
    val text = env.socketTextStream("localhost", 9999)

    val counts = text.flatMap { _.toLowerCase.split("\\W+") filter { _.nonEmpty } }
      .map { (_, 1) }
      .keyBy(0)
      .timeWindow(Time.seconds(5))
      .sum(1)

    counts.print()

    env.execute("Window Stream WordCount")
  }
}

批处理程序:【补充参考

import org.apache.flink.api.scala._

object WordCount {
  def main(args: Array[String]) {

    val env = ExecutionEnvironment.getExecutionEnvironment
    val text = env.fromElements(
      "Who's there?",
      "I think I hear them. Stand, ho! Who's there?")

    val counts = text.flatMap { _.toLowerCase.split("\\W+") filter { _.nonEmpty } }
      .map { (_, 1) }
      .groupBy(0)
      .sum(1)

    counts.print()
  }
}

从上面我们看出批处理和流处理他们获取实例都是通过getExecutionEnvironment方法,而StreamExecutionEnvironment代表的是流处理。ExecutionEnvironment代表的是批处理。

数据源
Sources是Flink从中获取数据的地方。  Flink支持许多预先实现的数据源功能。 它还支持编写自定义数据源函数,因此可以轻松编程任何不受支持的函数。 首先让我们尝试理解内置的源函数。

由于以前版本中,Flink只有流处理,因此下面是介绍的Flink1.7以前的版本,大体了解即可

Flink以前版本

DataStream API
基于Socket
DataStream API支持从套接字读取数据。 只需指定要从中读取数据的主机和端口,它就可以完成工作:

socketTextStream(hostName, port);

还可以选择指定分隔符:

socketTextStream(hostName,port,delimiter)

还可以指定API尝试获取数据的最大次数:

socketTextStream(hostName,port,delimiter,maxRetry)

基于文件
还可以选择使用Flink中基于文件的源函数从文件源流式传输数据。 可以使用readTextFile(String path)从路径中指定的文件中流式传输数据。 默认情况下,它将读取TextInputFormat并逐行读取字符串。
如果文件格式不是文本,则可以使用以下函数指定相同的格式:

readFile(FileInputFormat<Out> inputFormat, String path)

Flink还支持,使用readFileStream()读取文件流

readFileStream(String filePath, long intervalMillis, FileMonitoringFunction.WatchType watchType)

只需指定文件路径,轮询文件路径的轮询间隔以及监视类型。 监控类型包括三种类型:
 

  • 当系统应仅处理新文件时使用FileMonitoringFunction.WatchType.ONLY_NEW_FILES
  • 当系统仅追加文件内容时使用FileMonitoringFunction.WatchType.PROCESS_ONLY_APPENDED
  • 当系统不仅要重新处理文件的追加内容而且还要重新处理文件中的先前内容时,将使用FileMonitoringFunction.WatchType.REPROCESS_WITH_APPENDED


如果文件不是文本文件,那么我们可以选择使用以下函数,它允许我们定义文件输入格式:

readFile(fileInputFormat, path, watchType, interval, pathFilter, typeInfo)

在内部,它将读取文件任务划分为两个子任务。 一个子任务仅根据给定的WatchType监视文件路径。 第二个子任务并行执行读取文件。监控文件路径的子任务是不是并行子任务。 它的工作是根据轮询间隔扫描文件路径并报告要处理的文件,拆分文件,并将拆分分配给相应的下游线程:

Flink1.7版本
DataStream API
source依然是程序从中读取输入的位置。 可以使用StreamExecutionEnvironment.addSource(sourceFunction)将源附加到程序。 Flink附带了许多预先实现的源函数,但可以通过-非并行Source实现SourceFunction,或者通过实现ParallelSourceFunction接口或为并行源扩展RichParallelSourceFunction来编写自己的自定义源。

可以从StreamExecutionEnvironment访问几个预定义的流源:
这里我们可以跟以前的版本比较增加Collection-based,一些函数页发生了变化。

基于文件
readTextFile(path) - 读取文本文件,即逐行读取,并将它们作为字符串返回。
readFile(fileInputFormat,path) - 按指定的文件输入格式指定读取(一次)文件。
readFile(fileInputFormat,path,watchType,interval,pathFilter) - 这是前两个内部调用的方法。 它根据给定的fileInputFormat读取路径中的文件。 根据提供的watchType,此source可以定期监控(每隔ms)新数据的路径(FileProcessingMode.PROCESS_CONTINUOUSLY),或者处理当前在路径中的数据并退出(FileProcessingMode.PROCESS_ONCE)。 使用pathFilter,用户可以进一步排除处理文件。这里篇幅有限更多信息可查看链接

基于Socket
socketTextStream  - 从socket读取。 元素可以用分隔符分隔。详细可查看上文

基于Collection
fromCollection(Seq) - 从Java Java.util.Collection创建数据流。 集合中的所有元素必须属于同一类型。

fromCollection(Iterator) - 从迭代器创建数据流。 该类指定迭代器返回的元素的数据类型。

fromElements(elements:_ *) - 从给定的对象序列创建数据流。 所有对象必须属于同一类型。

fromParallelCollection(SplittableIterator) - 并行的从迭代器创建数据流。 该类指定迭代器返回的元素的数据类型。

generateSequence(from,to) - 并行生成给定间隔中的数字序列。


自定义
addSource  - 附加新的source函数。 例如,要从Apache Kafka读取,可以使用addSource(new FlinkKafkaConsumer08 <>(...))。 请参阅连接器以获取更多内容。

由于Flink1.7最新版本,这里也把DataSet API
补充上:
DataSet API


DataSet API 跟DataStream API 既有相同也有区别。

基于文件
readTextFile(path)/ TextInputFormat  - 按行读取文件并将它们作为字符串返回。

readTextFileWithValue(path)/ TextValueInputFormat  - 按行读取文件并将它们作为StringValues返回。 StringValues是可变字符串。

readCsvFile(path)/ CsvInputFormat  - 解析逗号(或其他字符)分隔字段的文件。 返回元组,案例类对象或POJO的DataSet。 支持基本java类型及其Value对应作为字段类型。

readFileOfPrimitives(path,delimiter)/ PrimitiveInputFormat  - 使用给定的分隔符解析新行(或其他char序列)分隔的原始数据类型(如String或Integer)的文件。

readSequenceFile(Key,Value,path)/ SequenceFileInputFormat  - 创建JobConf并从指定路径读取文件,类型为SequenceFileInputFormat,Key class和Value类,并将它们返回为Tuple2 <Key,Value>。

基于Collection
fromCollection(Seq) - 从Seq创建数据集。 集合中的所有元素必须属于同一类型。

fromCollection(Iterator) - 从迭代器创建数据集。 该类指定迭代器返回的元素的数据类型。

fromElements(elements:_ *) - 根据给定的对象序列创建数据集。 所有对象必须属于同一类型。

fromParallelCollection(SplittableIterator) - 并行地从迭代器创建数据集。 该类指定迭代器返回的元素的数据类型。

generateSequence(from,to) - 并行生成给定间隔中的数字序列。

通用
readFile(inputFormat,path)/ FileInputFormat  - 接受文件输入格式。

createInput(inputFormat)/ InputFormat  - 接受通用输入格式。

例子:

val env  = ExecutionEnvironment.getExecutionEnvironment

// read text file from local files system
val localLines = env.readTextFile("file:///path/to/my/textfile")

// read text file from a HDFS running at nnHost:nnPort
val hdfsLines = env.readTextFile("hdfs://nnHost:nnPort/path/to/my/textfile")

// read a CSV file with three fields
val csvInput = env.readCsvFile[(Int, String, Double)]("hdfs:///the/CSV/file")

// read a CSV file with five fields, taking only two of them
val csvInput = env.readCsvFile[(String, Double)](
  "hdfs:///the/CSV/file",
  includedFields = Array(0, 3)) // take the first and the fourth field

// CSV input can also be used with Case Classes
case class MyCaseClass(str: String, dbl: Double)
val csvInput = env.readCsvFile[MyCaseClass](
  "hdfs:///the/CSV/file",
  includedFields = Array(0, 3)) // take the first and the fourth field

// read a CSV file with three fields into a POJO (Person) with corresponding fields
val csvInput = env.readCsvFile[Person](
  "hdfs:///the/CSV/file",
  pojoFields = Array("name", "age", "zipcode"))

// create a set from some given elements
val values = env.fromElements("Foo", "bar", "foobar", "fubar")

// generate a number sequence
val numbers = env.generateSequence(1, 10000000)

// read a file from the specified path of type SequenceFileInputFormat
val tuples = env.readSequenceFile(classOf[IntWritable], classOf[Text],
"hdfs://nnHost:nnPort/path/to/file")

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值