Flink之UDF

151 阅读2分钟

实现UDF函数,实现更细粒度的控制。

1. 函数类(Function Classes)

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

  1. 下面的例子实现FilterFunction接口
    class FilterFilter extends FilterFunction[String] {
          override def filter(value: String): Boolean = {
            value.contains("flink")
          }
    }
    val flinkTweets = tweets.filter(new FlinkFilter)
    
  2. 将函数实现成匿名类
    //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")
            }
        }
    )
    
  3. 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的连接。
    }
}