实现UDF函数,实现更细粒度的控制。
1. 函数类(Function Classes)
Flink暴露了所有udf函数的接口(实现方式为接口或者抽象类)。例如MapFunction, FilterFunction, ProcessFunction等等。
- 下面的例子实现FilterFunction接口
class FilterFilter extends FilterFunction[String] { override def filter(value: String): Boolean = { value.contains("flink") } } val flinkTweets = tweets.filter(new FlinkFilter) - 将函数实现成匿名类
//RichFilterFunction是抽象类实现FilterFunction接口 //public abstract class RichFilterFunction<T> extends AbstractRichFunction implements FilterFunction<T> val flinkTweets = tweets.filter( new RichFilterFunction[String] { override def filter(value: String): Boolean = { value.contains("flink") } } ) - 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. 匿名函数类(Lambda Functions)
val tweets: DataStream[String] = ...
val flinkTweets = tweets.filter(_.contains("flink"))
3. 富函数
“富函数”是DataStream API提供的一个函数类的接口,所有Flink函数类都有其Rich版本。它与常规函数的不同在于,可以获取运行环境的上下文,并拥有一些生命周期方法,所以可以实现更复杂的功能。
- RichMapFunction
- RichFlatMapFunction
- RichFilterFunction
- …
Rich Function有一个生命周期的概念。典型的生命周期方法有:
- open()方法是rich function的初始化方法,当一个算子例如map或者filter被调用之前open()会被调用。
- close()方法是生命周期中的最后一个调用的方法,做一些清理工作。
- getRuntimeContext()方法提供了函数的RuntimeContext的一些信息,例如函数执行的并行度,任务的名字,以及state状态
RichFlatMapFunction实例:
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的连接。
}
}