前言
本文主要讲解下窗口函数:ReduceFunction,AggregateFunction,ProcessWindowFunction
ReduceFunction
是个增量计算的算子,数据来一条算一条,要求入参和出参类型一致这个要求导致条件苛刻。没有aggregate好用~
直接看代码:模拟订单,计算10s滚动窗口订单金额~~~使用起来比较简单的
package com.realtime.flink.function
import com.realtime.flink.dto.OrderDto
import com.realtime.flink.source.OrderSource
import org.apache.flink.api.common.functions.ReduceFunction
import org.apache.flink.streaming.api.scala.StreamExecutionEnvironment
import org.apache.flink.streaming.api.scala._
import org.apache.flink.streaming.api.windowing.assigners.{GlobalWindows, TumblingEventTimeWindows, TumblingProcessingTimeWindows}
import org.apache.flink.streaming.api.windowing.time.Time
/**
* 注意:reduce不能直接用Double,会报错
* 数据时增量计算,来一条算一条
*/
object ReduceFunctionTest {
def main(args: Array[String]): Unit = {
val env = StreamExecutionEnvironment.getExecutionEnvironment
env.getConfig.setParallelism(1)
env.addSource(new OrderSource)
.windowAll(TumblingProcessingTimeWindows.of(Time.seconds(10)))
.reduce(new ReduceFunction[OrderDto] {
override def reduce(value1: OrderDto, value2: OrderDto): OrderDto = {
value1.setOrderPrice(value1.getOrderPrice+value2.getOrderPrice)
value1
}
})
.map(x=>{
println(x.getOrderPrice)
})
env.execute("tttt")
}
}
输出结果:
AAAAAAAAAAA数据:2021-03-30 23:22:34-->1
AAAAAAAAAAA数据:2021-03-30 23:22:35-->7
AAAAAAAAAAA数据:2021-03-30 23:22:36-->4
AAAAAAAAAAA数据:2021-03-30 23:22:37-->9
AAAAAAAAAAA数据:2021-03-30 23:22:38-->7
AAAAAAAAAAA数据:2021-03-30 23:22:39-->1
29.0
AAAAAAAAAAA数据:2021-03-30 23:22:40-->6
AAAAAAAAAAA数据:2021-03-30 23:22:41-->1
AAAAAAAAAAA数据:2021-03-30 23:22:42-->6
AAAAAAAAAAA数据:2021-03-30 23:22:43-->6
AAAAAAAAAAA数据:2021-03-30 23:22:44-->5
AAAAAAAAAAA数据:2021-03-30 23:22:45-->4
AAAAAAAAAAA数据:2021-03-30 23:22:46-->3
AAAAAAAAAAA数据:2021-03-30 23:22:47-->6
AAAAAAAAAAA数据:2021-03-30 23:22:48-->9
AAAAAAAAAAA数据:2021-03-30 23:22:49-->0
46.0
AAAAAAAAAAA数据:2021-03-30 23:22:50-->8
AAAAAAAAAAA数据:2021-03-30 23:22:51-->7
AAAAAAAAAAA数据:2021-03-30 23:22:52-->0
AggregateFunction
也是个增量计算的算子,里面实现4个方法,也比较简单,用起来会比reduce更灵活。具体看代码注释~
package com.realtime.flink.function
import com.realtime.flink.dto.OrderDto
import com.realtime.flink.source.OrderSource
import org.apache.flink.api.common.functions.{AggregateFunction, ReduceFunction}
import org.apache.flink.streaming.api.scala.{StreamExecutionEnvironment, _}
import org.apache.flink.streaming.api.windowing.assigners.TumblingProcessingTimeWindows
import org.apache.flink.streaming.api.windowing.time.Time
/**
* 数据时增量计算,来一条算一条
*/
object AggregateFunctionTest {
def main(args: Array[String]): Unit = {
val env = StreamExecutionEnvironment.getExecutionEnvironment
env.getConfig.setParallelism(1)
env.addSource(new OrderSource)
.windowAll(TumblingProcessingTimeWindows.of(Time.seconds(10)))
.aggregate(new AggregateFunction[OrderDto,Double,Double] {
// 初始化
override def createAccumulator(): Double = {
0.0
}
// 窗口数据进来合并
override def add(value: OrderDto, accumulator: Double): Double = {
value.getOrderPrice+accumulator
}
// 返回结果
override def getResult(accumulator: Double): Double = {
accumulator
}
// 窗口合并,多并发情况下多个窗口结果合并输出,测试用例设置了并发数据为 1
override def merge(a: Double, b: Double): Double = {
a+b
}
})
.print()
env.execute("tttt")
}
}
测试结果:
AAAAAAAAAAA数据:2021-03-30 23:34:23-->1
AAAAAAAAAAA数据:2021-03-30 23:34:24-->1
AAAAAAAAAAA数据:2021-03-30 23:34:25-->2
AAAAAAAAAAA数据:2021-03-30 23:34:26-->1
AAAAAAAAAAA数据:2021-03-30 23:34:27-->7
AAAAAAAAAAA数据:2021-03-30 23:34:28-->2
AAAAAAAAAAA数据:2021-03-30 23:34:29-->0
14.0
AAAAAAAAAAA数据:2021-03-30 23:34:30-->6
AAAAAAAAAAA数据:2021-03-30 23:34:31-->5
AAAAAAAAAAA数据:2021-03-30 23:34:32-->9
AAAAAAAAAAA数据:2021-03-30 23:34:33-->3
AAAAAAAAAAA数据:2021-03-30 23:34:34-->7
AAAAAAAAAAA数据:2021-03-30 23:34:35-->7
AAAAAAAAAAA数据:2021-03-30 23:34:36-->3
AAAAAAAAAAA数据:2021-03-30 23:34:37-->1
AAAAAAAAAAA数据:2021-03-30 23:34:38-->1
AAAAAAAAAAA数据:2021-03-30 23:34:39-->6
48.0
AAAAAAAAAAA数据:2021-03-30 23:34:40-->4
AAAAAAAAAAA数据:2021-03-30 23:34:41-->4
ProcessWindowFunction
全量计算,窗口数据到齐后才计算,容易出现内存溢出。在大量的数据情况下单独使用不合适。可以搭配上面两个增量计算一起使用。他的优势在于能拿到窗口相关的信息。
测试用例:
package com.realtime.flink.function
import com.realtime.flink.dto.OrderDto
import com.realtime.flink.source.OrderSource
import org.apache.flink.api.common.functions.AggregateFunction
import org.apache.flink.streaming.api.scala.function.ProcessAllWindowFunction
import org.apache.flink.streaming.api.scala.{StreamExecutionEnvironment, _}
import org.apache.flink.streaming.api.windowing.assigners.TumblingProcessingTimeWindows
import org.apache.flink.streaming.api.windowing.time.Time
import org.apache.flink.streaming.api.windowing.windows.TimeWindow
import org.apache.flink.util.Collector
/**
* 全量计算,窗口数据到齐后才计算,容易出现内存溢出。在大量的数据情况下单独使用不合适
* 优势:context中有window和windowState
*/
object ProcessFunctionTest {
def main(args: Array[String]): Unit = {
val env = StreamExecutionEnvironment.getExecutionEnvironment
env.getConfig.setParallelism(1)
env.addSource(new OrderSource)
.windowAll(TumblingProcessingTimeWindows.of(Time.seconds(10)))
.process(new ProcessAllWindowFunction[OrderDto,Double,TimeWindow] {
override def process(context: Context, elements: Iterable[OrderDto], out: Collector[Double]): Unit = {
println("当前最大时间窗口:"+context.window.maxTimestamp())
val ite = elements.iterator
var result = 0.0
while (ite.hasNext){
result = result+ite.next().getOrderPrice
}
out.collect(result)
}
})
.print()
env.execute("tttt")
}
}
结果:
AAAAAAAAAAA数据:2021-03-30 23:41:04-->9
AAAAAAAAAAA数据:2021-03-30 23:41:05-->2
AAAAAAAAAAA数据:2021-03-30 23:41:06-->2
AAAAAAAAAAA数据:2021-03-30 23:41:07-->9
AAAAAAAAAAA数据:2021-03-30 23:41:08-->1
AAAAAAAAAAA数据:2021-03-30 23:41:09-->2
当前最大时间窗口:1617118869999
25.0
AAAAAAAAAAA数据:2021-03-30 23:41:10-->6
AAAAAAAAAAA数据:2021-03-30 23:41:11-->6
AAAAAAAAAAA数据:2021-03-30 23:41:12-->7
AAAAAAAAAAA数据:2021-03-30 23:41:13-->4
AAAAAAAAAAA数据:2021-03-30 23:41:14-->0
AAAAAAAAAAA数据:2021-03-30 23:41:15-->2
AAAAAAAAAAA数据:2021-03-30 23:41:16-->6
AAAAAAAAAAA数据:2021-03-30 23:41:17-->6
AAAAAAAAAAA数据:2021-03-30 23:41:18-->6
AAAAAAAAAAA数据:2021-03-30 23:41:19-->1
当前最大时间窗口:1617118879999
44.0
AAAAAAAAAAA数据:2021-03-30 23:41:20-->2
AAAAAAAAAAA数据:2021-03-30 23:41:21-->6
AAAAAAAAAAA数据:2021-03-30 23:41:22-->0
总结
本文比较简单介绍了三个窗口函数的使用。后面文章会接着讲解下 windowstate使用以及增量全量窗口函数的配合使用~~