Java 弗林克:有没有其他方法来计算平均值和状态变量,而不是使用RichAggregateFunction?

Java 弗林克:有没有其他方法来计算平均值和状态变量,而不是使用RichAggregateFunction?,java,apache-flink,Java,Apache Flink,我不确定我必须使用哪个stream Flink转换来计算某个流的平均值,并在5秒内更新一个状态(假设它是一个INT数组,我的状态)。 如果我使用RichFlatMapFunction我可以计算平均值并更新数组状态。但是,我必须打电话 streamSource .keyBy(0) .flatMap(new MyRichFlatMapFunction()) .print() 我不能把它写在窗户上。 如果我使用 streamSource .keyBy(0) .

我不确定我必须使用哪个stream Flink转换来计算某个流的平均值,并在5秒内更新一个状态(假设它是一个INT数组,我的状态)。 如果我使用
RichFlatMapFunction
我可以计算平均值并更新数组状态。但是,我必须打电话

streamSource
    .keyBy(0)
    .flatMap(new MyRichFlatMapFunction())
    .print()
我不能把它写在窗户上。 如果我使用

streamSource
    .keyBy(0)
    .window(TumblingProcessingTimeWindows.of(Time.seconds(5)))
    .aggregate(new MyAggregateFunction())
    .print()
我无法通过
ValueState
保持数组状态

我试图使用
RichAggregateFunction
,但我遇到了与此线程相同的问题。有没有其他方法来计算平均值并跟踪Flink中的另一个状态

在弗林克,我将如何处理这个问题? 以下是我尝试的方法,但实际上不起作用>

streamStations.filter(新的传感器过滤器(“计数”)
.map(新火车站地图())
.keyBy(新的MyKeySelector())
.window(tumblingeventimeewindows.of(Time.seconds(5));
//这个集合不起作用
//.aggregate(新的AverageRichAggregator())
//.print();
公共静态类AverageRichAggregator扩展
RichAggregateFunction{
私有静态最终长serialVersionUID=-4087448912082797L;
私有字符串函数名;
私人价值州countMinSketchState;
@凌驾
公共void open(配置参数)引发异常{
ValueStateDescriptor描述符=新的ValueStateDescriptor(“countMinSketchState”,
CountMinSketch.class);
this.countMinSketchState=getRuntimeContext().getState(描述符);
}
@凌驾
公共元组3 createAccumulator(){
this.countMinSketchState.clear();
返回新的Tuple3(0.0,0L,0);
}
@凌驾
公共元组3添加(
Tuple3值,
三元组(累加器){
试一试{
if(value.f1.f1等于(“COUNT_PE”)){
//int count=(int)Math.round(value.f2);
//countMinSketch.updateSketchAsync(“COUNT_PE”);
}else if(value.f1.f1.equals(“COUNT_TI”)){
//int count=(int)Math.round(value.f2);
//countMinSketch.updateSketchAsync(“COUNT_TI”);
}else if(value.f1.f1.equals(“COUNT_TR”)){
//int count=(int)Math.round(value.f2);
//countMinSketch.updateSketchAsync(“COUNT_TR”);
}
CountMinSketch currentCountMinSketchState=this.countMinSketchState.value();
currentCountMinSketchState.UpdateSketchSync(值为.f1.f1);
this.countMinSketchState.update(currentCountMinSketchState);
}捕获(IOE异常){
e、 printStackTrace();
}
返回新的Tuple3(acculator.f0+value.f2,acculator.f1+1L,value.f1.f4);
}
@凌驾
公共Tuple2 getResult(Tuple3累加器){
字符串标签=”;
整数频率=0;
试一试{
if(functionName.equals(“COUNT_PE”)){
label=“火车站平均人数”;
//frequency=countMinSketch.getFrequencyFromSketch(“COUNT_PE”);
}else if(functionName.equals(“COUNT_TI”)){
标签=“火车站平均车票”;
//frequency=countMinSketch.getFrequencyFromSketch(“COUNT_TI”);
}else if(functionName.equals(“COUNT_TR”)){
标签=“列车在火车站的平均值”;
//frequency=countMinSketch.getFrequencyFromSketch(“COUNT_TR”);
}
frequency=this.countMinSketchState.value().getFrequencyFromSketch(函数名);
}捕获(IOE异常){
e、 printStackTrace();
}
返回新的元组2(标签+“[”+accumulator.f2+”]读取[“+频率+”],
((双)累加器.f0)/累加器.f1);
}
@凌驾
公共元组3合并(元组3 a、元组3 b){
返回新的Tuple3(a.f0+b.f0,a.f1+b.f1,a.f2);
}
}
错误:

Exception in thread "main" java.lang.UnsupportedOperationException: This aggregation function cannot be a RichFunction.
    at org.apache.flink.streaming.api.datastream.WindowedStream.aggregate(WindowedStream.java:692)
    at org.sense.flink.examples.stream.MultiSensorMultiStationsReadingMqtt2.<init>(MultiSensorMultiStationsReadingMqtt2.java:71)
    at org.sense.flink.App.main(App.java:141)
线程“main”java.lang.UnsupportedOperationException中的异常:此聚合函数不能是RichFunction。 位于org.apache.flink.streaming.api.datastream.WindowedStream.aggregate(WindowedStream.java:692) 位于org.sense.flink.examples.stream.MultiSensorMultiStationsReadingMqtt2。(MultiSensorMultiStationsReadingMqtt2.java:71) 位于org.sense.flink.App.main(App.java:141)
谢谢,聚合器不允许保持任意状态,以防聚合器可能与合并窗口一起使用——因为Flink不知道如何合并您的临时状态

但您可以将AggregateFunction与ProcessWindowFunction组合,如下所示:

input
 .keyBy(<key selector>)
 .timeWindow(<duration>)
 .aggregate(new MyAggregateFunction(), new MyProcessWindowFunction());
输入
.keyBy()
.timeWindow()
.aggregate(新的MyAggregateFunction(),新的MyProcessWindowFunction());
ProcessWindowFunction的process方法将被传递一个迭代器,该迭代器只包含预聚合的结果和一个。希望这将以一种简单的方式提供您所需要的。但是,如果您需要用每个到达的记录更新自己的状态,那么您需要扩展聚合器管理的类型以适应这种情况

以下是如何使用全局状态的大致概述:

private static class MyWindowFunction extends ProcessWindowFunction<IN, OUT, KEY, TimeWindow> {
    private final static ValueStateDescriptor<Long> myGlobalState =
      new ValueStateDescriptor<>("stuff", LongSerializer.INSTANCE);

    @Override
    public void process(KEY key, Context context, Iterable<IN> values,  Collector<OUT> out) {
        ValueState<Long> goodStuff = context.globalState().getState(myGlobalState);
    }
}
私有静态类MyWindowFunction扩展了ProcessWindowFunction{
私有最终静态值StateDescriptor myGlobalState=
新的ValueStateDescriptor(“stuff”,lonserializer.INSTANCE);
@凌驾
公共void进程(键、上下文上下文、Iterable值、收集器输出){
ValueState goodStuff=context.g
private static class MyWindowFunction extends ProcessWindowFunction<IN, OUT, KEY, TimeWindow> {
    private final static ValueStateDescriptor<Long> myGlobalState =
      new ValueStateDescriptor<>("stuff", LongSerializer.INSTANCE);

    @Override
    public void process(KEY key, Context context, Iterable<IN> values,  Collector<OUT> out) {
        ValueState<Long> goodStuff = context.globalState().getState(myGlobalState);
    }
}