Flink 中的 Window Assigners(窗口分配器)

Window Assigners

指定流是否为keyed之后,下一步是定义Window Assigner。Window Assigners定义了如何将元素分配给Window。这是通过window (...)(对于keyed流)或windowAll()(对于非keyed流)调用中指定您选择的WindowAssihner来完成的。

WindowAssigner负责将每个传入元素分配给一个或多个窗口。Flink为最常见的用例提供了预定义的窗口分配器,即滚动窗口,滑动窗口,会话窗口和全局窗口。还可以通过扩展WindowAssigner类来实现自定义窗口分配器。所有内置窗口分配器(全局窗口除外)均根据时间将元素分配给窗口,时间可以是处理时间,也可以是事件时间。

基于时间的窗口具有开始时间戳(包括端点)和结束时间戳(排除端点),他们共同描述了窗口的大小。在代码中,Flink在使用基于时间的窗口时使用TimeWindow,该窗口具有用于查询开始时间戳和结束时间戳的方法,以及用于返回给定窗口的最大允许时间戳的附加方法maxTimestamp ()

Tumbling Windows

滚动窗口分配器将每个元素分配给在指定窗口大小的窗口。滚动窗口具有固定的大小,并且不重叠。
在这里插入图片描述

env.socketTextStream("Spark", 9999)
  .flatMap(_.split("\\s+"))
  .map((_,1))
  .keyBy(t =>t._1)
  .window(TumblingProcessingTimeWindows.of(Time.seconds(5)))
  .reduce((v1,v2)=>(v1._1,v1._2+v2._2))
  .print()

Sliding Windows

滑动窗口分配器将元素分配给固定长度的窗口。类似于滚动窗口分配器,窗口的大小由窗口大小参数配置。附加的窗口滑动参数控制滑动窗口启动的频率。因此,如果滑动间隔小于窗口大小,则滑动窗口可能会重叠。在这种情况下,元素被分配给多个窗口。

在这里插入图片描述

env.socketTextStream("CentOS", 9999)
  .flatMap(_.split("\\s+"))
  .map((_,1))
  .keyBy(t =>t._1)
  .window(SlidingProcessingTimeWindows.of(Time.seconds(10), Time.seconds(5)))
  .aggregate(new AggregateFunction[(String,Int),(String,Int),(String,Int)]{
    
    
    override def createAccumulator(): (String, Int) = ("",0)
      override def add(value: (String, Int), accumulator: (String, Int)): (String, Int) = (value._1,value._2+accumulator._2)
      override def getResult(accumulator: (String, Int)): (String, Int) = accumulator
      override def merge(a: (String, Int), b: (String, Int)): (String, Int) = (a._1,a._2+b._2)
  })
  .print()

Session Windows

会话窗口分配器按活动会话对元素进行分组。与滚动窗口和滑动窗口相比,会话窗口不重叠且没有固定的开始和结束时间。相反,当会话窗口在一定时间段内未接收到元素时(发生不活动间隙时),它将关闭。会话窗口分配器可以配置有静态会话间隔,也可以配置有会话间隔提取器功能,该功能定义不活动的时间长度。当该时间段到期时,当前会话关闭,随后的元素被分配给新的会话窗口。

在这里插入图片描述

//import org.apache.flink.streaming.api.scala.function.WindowFunction
class UserDefineWindowFunction extends WindowFunction[(String,Int),String,String,TimeWindow]{
    
    
  override def apply(key: String,
                     window: TimeWindow, 
                     input: Iterable[(String, Int)], 
                     out: Collector[String]): Unit = {
    
    
    val sdf = new SimpleDateFormat("HH:mm:ss")
    val start = sdf.format(window.getStart)
    val end = sdf.format(window.getEnd)
    var maxTimestamp=sdf.format(window.maxTimestamp())
    println(s"key:${key},start:${start},end:${end},maxTimestamp:"+maxTimestamp)
    out.collect(s"${key},${input.map(_._2).sum}")
  }
}

Global Windows

全局窗口分配器将具有相同键的元素分配给同一单个全局窗口。仅当指定自定义触发器时,此窗口方案才有用。否则,将不会执行任何计算,因为全局窗口没有可以处理聚合元素的自然终点(因为该窗口的触发器使用的是Never Trigger)

在这里插入图片描述

class UserDefineProcessWindowFunction extends ProcessWindowFunction[(String,Int),String,String,GlobalWindow]{
    
    
  override def process(key: String,
                       context: Context,
                       elements: Iterable[(String, Int)],
                       out: Collector[String]): Unit = {
    
    

    out.collect(s"${key},${elements.toList.map(_._2).sum}")
  }
}
 env.socketTextStream("CentOS", 9999)
        .flatMap(_.split("\\s+"))
        .map((_,1))
        .keyBy(t =>t._1)
        .window(GlobalWindows.create())
        .trigger( CountTrigger.of(4))
        .process(new UserDefineProcessWindowFunction)
        .print()

猜你喜欢

转载自blog.csdn.net/gym02/article/details/105881109