1.基础函数类
Flink 暴露了所有udf 函数的接口(实现方式为接口或者抽象类)。例如MapFunction, FilterFunction等等。这里以FilterFunction为例:
无参的如下:
val dataStream = inputStream
.map(data => {
val arr = data.split(",")
SensorReading(arr(0), arr(1).toLong, arr(2).toDouble)
})
.filter(new MyFilter)
class MyFilter extends FilterFunction[SensorReading] {
override def filter(value: SensorReading): Boolean =
value.id.startsWith("sensor_1")
}
有参的如下:
val dataStream = inputStream
.map( data => {
val arr = data.split(",")
SensorReading(arr(0), arr(1).toLong, arr(2).toDouble)
} ).filter(new MyFilter("sensor"))
class MyFilter(name:String) extends FilterFunction[SensorReading]{
override def filter(value: SensorReading): Boolean =
value.id.startsWith(name)
}
等价于
val dataStream = inputStream
.map( data => {
val arr = data.split(",")
SensorReading(arr(0), arr(1).toLong, arr(2).toDouble)
} ).filter(new FilterFunction[SensorReading] {
override def filter(t: SensorReading): Boolean = t.id.startsWith("sensor")
})
如下所示,FilterFunction只有传入参数的类型,返回类型为Boolan类型。MapFunction既有传入参数类型,又有传出参数类型
public interface FilterFunction<T> extends Function, Serializable {
boolean filter(T var1) throws Exception;
}
public interface MapFunction<T, O> extends Function, Serializable {
O map(T var1) throws Exception;
}
2.富函数
2.1基础富函数
“富函数”是DataStream API 提供的一个函数类的接口,所有Flink 函数类都有其Rich 版本。它与常规函数的不同在于,可以获取运行环境的上下文,并拥有一些生命周期方法,所以可以实现更复杂的功能。简单的可以概括如下:
在函数处理数据之前,需要做一些初始化的工作;或者需要在处理数据时可以获得函数执行上下文的一些信息;以及在处理完数据时做一些清理工作。
例如:RichMapFunction、RichFlatMapFunction、 RichFilterFunction......
Rich Function 有一个生命周期的概念。典型的生命周期方法有:
- open()方法是rich function 的初始化方法,当一个算子例如map 或者filter被调用之前open()会被调用。
- close()方法是生命周期中的最后一个调用的方法,做一些清理工作。
- getRuntimeContext()方法提供了函数的RuntimeContext 的一些信息,例如函数执行的并行度,任务的名字,以及state 状态。
示例代码
// 富函数,可以获取到运行时上下文,还有一些生命周期
class MyRichMapper extends RichMapFunction[SensorReading, String]{
// getRuntimeContext()方法提供了函数的RuntimeContext的一些信息,例如函数执行的并行度,当前子任务的索引,当前子任务的名字。同时还它还包含了访问分区状态的方法
lazy val listState: ListState[Int] = getRuntimeContext.getListState(new ListStateDescriptor[Int]("liststate", classOf[Int]))
lazy val mapState: MapState[String, Double] = getRuntimeContext.getMapState(new MapStateDescriptor[String, Double]("mapstate", classOf[String], classOf[Double]))
override def open(parameters: Configuration): Unit = {
// 做一些初始化操作,比如数据库的连接
// getRuntimeContext
}
override def map(value: SensorReading): String = value.id + " temperature"
override def close(): Unit = {
// 一般做收尾工作,比如关闭连接,或者清空状态
}
}