Flink笔记8:Flink流处理API之支持的数据类型和UDF 函数

1、支持的数据类型

Flink 流应用程序处理的是以数据对象表示的事件流。所以在Flink 内部,我们需要能够处理这些对象。它们需要被序列化和反序列化,以便通过网络传送它们;或者从状态后端、检查点和保存点读取它们。为了有效地做到这一点,Flink 需要明确知道应用程序所处理的数据类型。Flink 使用类型信息的概念来表示数据类型,并为每个数据类型生成特定的序列化器、反序列化器和比较器。

Flink 还具有一个类型提取系统,该系统分析函数的输入和返回类型,以自动获取类型信息,从而获得序列化器和反序列化器。但是,在某些情况下,例如lambda函数或泛型类型,需要显式地提供类型信息,才能使应用程序正常工作或提高其性能。

Flink 支持Java 和Scala 中所有常见数据类型。使用最广泛的类型有以下几种。

1.1 基础数据类型

Flink 支持所有的Java 和Scala 基础数据类型,Int, Double, Long, String, …

val numbers: DataStream[Long] = env.fromElements(1L, 2L, 3L, 4L)
numbers.map( n => n + 1 )

1.2 Java 和Scala 元组(Tuples)

val persons: DataStream[(String, Integer)] = env.fromElements(
("Adam", 17),
("Sarah", 23) )
persons.filter(p => p._2 > 18)

1.3 Scala 样例类(case classes)

case class Person(name: String, age: Int)

val persons: DataStream[Person] = env.fromElements(
Person("Adam", 17),
Person("Sarah", 23) )
persons.filter(p => p.age > 18)

1.4 Java 简单对象(POJOs)

public class Person {
  public String name;
  public int age;
  public Person() {}
  public Person(String name, int age) {
    this.name = name;
    this.age = age;
  }
}


DataStream<Person> persons = env.fromElements(
new Person("Alex", 42),
new Person("Wendy", 23));

1.5 其它(Arrays, Lists, Maps, Enums, 等等)

Flink 对Java 和Scala 中的一些特殊目的的类型也都是支持的,比如Java 的ArrayList,HashMap,Enum 等等。

2、UDF 函数——更细粒度的控制流

2.1 函数类(Function Classes)

Flink 暴露了所有udf 函数的接口(实现方式为接口或者抽象类)。例如MapFunction, FilterFunction, ProcessFunction 等等。

下面例子实现了FilterFunction 接口:

// 自定义一个函数类
class MyFilter extends FilterFunction[SensorReading]{
  override def filter(value: SensorReading): Boolean =
    value.id.startsWith("sensor_1")
}

val flinkTweets = tweets.filter(new MyFilter)

还可以将函数实现成匿名类

val flinkTweets = tweets.filter(
  new RichFilterFunction[String] {
    override def filter(value: String): Boolean = {
      value.id.startsWith("sensor_1")
    }
  })

我们filter 的字符串"flink"还可以当作参数传进去。

val tweets: DataStream[String] = ...
val flinkTweets = tweets.filter(new KeywordFilter("flink"))
class KeywordFilter(keyWord: String) extends FilterFunction[String] {
  override def filter(value: String): Boolean = {
    value.contains(keyWord)
  }
}

2.2 匿名函数(Lambda Functions)

val tweets: DataStream[String] = ...
val flinkTweets = tweets.filter(_.contains("flink"))

2.3 富函数(Rich Functions)

“富函数”是DataStream API 提供的一个函数类的接口,所有Flink 函数类都有其Rich 版本。它与常规函数的不同在于,可以获取运行环境的上下文,并拥有一些生命周期方法,所以可以实现更复杂的功能。

RichMapFunction
RichFlatMapFunction
RichFilterFunction

Rich Function 有一个生命周期的概念。典型的生命周期方法有:

  • open()方法是rich function 的初始化方法,当一个算子例如map 或者filter被调用之前open()会被调用。
  • close()方法是生命周期中的最后一个调用的方法,做一些清理工作。
  • getRuntimeContext()方法提供了函数的RuntimeContext 的一些信息,例如函数执行的并行度,任务的名字,以及state 状态
class MyFlatMap extends RichFlatMapFunction[Int, (Int, Int)] {
  var subTaskIndex = 0
  override def open(configuration: Configuration): Unit = {
    subTaskIndex = getRuntimeContext.getIndexOfThisSubtask
    // 以下可以做一些初始化工作,例如建立一个和HDFS 的连接
  }
  override def flatMap(in: Int, out: Collector[(Int, Int)]): Unit = {
    if (in % 2 == subTaskIndex) {
      out.collect((subTaskIndex, in))
    }
  }
  override def close(): Unit = {
    // 以下做一些清理工作,例如断开和HDFS 的连接。
  }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值