Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/401.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java ApacheFlink-事件时间窗口_Java_Apache Flink_Stream Processing - Fatal编程技术网

Java ApacheFlink-事件时间窗口

Java ApacheFlink-事件时间窗口,java,apache-flink,stream-processing,Java,Apache Flink,Stream Processing,我想在ApacheFlink中创建键控窗口,这样每个键的窗口在键的第一个事件到达n分钟后执行。是否可以使用事件时间特性来完成(因为处理时间取决于系统时钟,并且不确定第一个事件何时到达)。如果可能,请解释事件时间和水印的分配,并解释如何在n分钟后调用process window函数 下面是代码的一部分,可以让您了解我目前正在做什么: //Make keyed events so as to start a window for a key Keyed

我想在ApacheFlink中创建键控窗口,这样每个键的窗口在键的第一个事件到达n分钟后执行。是否可以使用事件时间特性来完成(因为处理时间取决于系统时钟,并且不确定第一个事件何时到达)。如果可能,请解释事件时间和水印的分配,并解释如何在n分钟后调用process window函数

下面是代码的一部分,可以让您了解我目前正在做什么:

            //Make keyed events so as to start a window for a key
            KeyedStream<SourceData, Tuple> keyedEvents = 
                    env.addSource(new MySource(configData),"JSON Source")
                    .assignTimestampsAndWatermarks(new MyTimeStamps())
                    .setParallelism(1)
                    .keyBy("service");


            //Start a window for windowTime time
            DataStream<ResultData> resultData=
                    keyedEvents
                    .timeWindow(Time.minutes(winTime))
                    .process(new ProcessEventWindow(configData))
                    .name("Event Collection Window")
                    .setParallelism(25);
编辑:用于分配时间戳和水印的类i

public class MyTimeStamps implements AssignerWithPeriodicWatermarks<SourceData> {

    @Override
    public long extractTimestamp(SourceData element, long previousElementTimestamp) {

          //Will return epoch of currentTime
        return GlobalUtilities.getCurrentEpoch();
    }

    @Override
    public Watermark getCurrentWatermark() {
        // TODO Auto-generated method stub
        //Will return epoch of currentTime + 10 minutes
        return new Watermark(GlobalUtilities.getTimeShiftNMinutesEpoch(10));
    }

}
公共类MyTimeStamps使用PeriodicWatermarks实现AssignerWithPeriodicWatermarks{
@凌驾
公共长提取时间戳(SourceData元素,长PreviousElement时间戳){
//将返回当前时间的纪元
返回GlobalUtilities.getCurrentEpoch();
}
@凌驾
公共水印getCurrentWatermark(){
//TODO自动生成的方法存根
//将返回currentTime的历元+10分钟
返回新水印(GlobalUtilities.getTimeShiftNMinutesEpoch(10));
}
}

不久前,关于事件时间窗口,我有一个类似的问题。下面是我的流的样子

val env = StreamExecutionEnvironment.getExecutionEnvironment
env.setStreamTimeCharacteristic(TimeCharacteristic.EventTime)

//Consumer Setup

val stream = env.addSource(consumer)
  .assignTimestampsAndWatermarks(new WMAssigner)

// Additional Setup here

stream
  .keyBy { data => data.findValue("service") }
  .window(TumblingEventTimeWindows.of(Time.minutes(10)))
  .process { new WindowProcessor }

  //Sinks go here
我的WMAssigner类如下所示(注意:这允许1分钟的无序事件发生,如果不想允许延迟,可以扩展不同的时间戳提取器):

我想用于水印的时间戳是data.ts字段

我的WindowProcessor:

class WindowProcessor extends ProcessWindowFunction[ObjectNode,String,String,TimeWindow] {
  override def process(key: String, context: Context, elements: Iterable[ObjectNode], out: Collector[String]): Unit = {
    val out = ""
    elements.foreach( value => {
      out = value.findValue("data").findValue("outData")
    }
    out.collect(out)
  }
}

如果有任何不清楚的地方请告诉我

我认为对于您的用例,最好使用。您可以做的是在第一个事件发生时注册一个EventTimeTimer。而不是在
onTimer
方法中发出结果

比如:

public class ProcessFunctionImpl extends ProcessFunction<SourceData, ResultData> {

    @Override
    public void processElement(SourceData value, Context ctx, Collector<ResultData> out)
        throws Exception {

        // retrieve the current aggregate
        ResultData current = state.value();
        if (current == null) {
            // first event arrived
            current = new ResultData();
            // register end of window
            ctx.timerService().registerEventTimeTimer(ctx.timestamp() + 10 * 60 * 1000 /* 10 minutes */);
        }

        // update the state's aggregate
        current += value;

        // write the state back
        state.update(current);
    }

    @Override
    public void onTimer(long timestamp, OnTimerContext ctx, Collector<ResultData> out)
        throws Exception {

        // get the state for the key that scheduled the timer
        ResultData result = state.value();

        out.collect(result);

        // reset the window state
        state.clear();
    }
}
公共类ProcessFunctionImpl扩展了ProcessFunction{
@凌驾
public void processElement(SourceData值、Context ctx、Collector out)
抛出异常{
//检索当前聚合
ResultData current=state.value();
如果(当前==null){
//第一件事到了
当前=新结果数据();
//注册窗口的末尾
ctx.timerService().registereventtimeter(ctx.timestamp()+10*60*1000/*10分钟*/);
}
//更新状态的聚合
电流+=值;
//回信
状态更新(当前);
}
@凌驾
公用void onTimer(长时间戳、OnTimerContext ctx、收集器输出)
抛出异常{
//获取调度计时器的密钥的状态
ResultData result=state.value();
收集(结果);
//重置窗口状态
state.clear();
}
}

感谢您的回复。请检查更新的问题。我希望窗口从第一个事件的事件时间开始运行10分钟。那么,我该如何为不同的键指定开始和结束窗口。感谢Dawid的回复。我尝试了你的解决方案,但集合进行了无限循环或其他操作(当我在10分钟后打印日期流时,它什么也没打印)。我想在活动时间分配方面存在一些问题,请您也解释一下。。我如何将事件时间分配给不同的事件,以实现所需的输出。您是否阅读了这些文档:?他们非常详细地描述了如何分配时间戳和水印。我已经阅读了文档,并以与文档中提到的类似的方式分配时间戳,但仍然遇到一些问题。如果你能给出一个真正有用的伪代码。我将用我的实现更新这个问题。@DawidWysakowicz我有一个相同的问题,我想在用户的第一个事件时间戳开始的30分钟内收集用户的所有事件,并对这些事件进行聚合,但我还有第二个条件,如果在30分钟内某个事件类型“开始”到达后,也会触发并启动一个新窗口。您能帮助解决这种类型的用例吗。
class WindowProcessor extends ProcessWindowFunction[ObjectNode,String,String,TimeWindow] {
  override def process(key: String, context: Context, elements: Iterable[ObjectNode], out: Collector[String]): Unit = {
    val out = ""
    elements.foreach( value => {
      out = value.findValue("data").findValue("outData")
    }
    out.collect(out)
  }
}
public class ProcessFunctionImpl extends ProcessFunction<SourceData, ResultData> {

    @Override
    public void processElement(SourceData value, Context ctx, Collector<ResultData> out)
        throws Exception {

        // retrieve the current aggregate
        ResultData current = state.value();
        if (current == null) {
            // first event arrived
            current = new ResultData();
            // register end of window
            ctx.timerService().registerEventTimeTimer(ctx.timestamp() + 10 * 60 * 1000 /* 10 minutes */);
        }

        // update the state's aggregate
        current += value;

        // write the state back
        state.update(current);
    }

    @Override
    public void onTimer(long timestamp, OnTimerContext ctx, Collector<ResultData> out)
        throws Exception {

        // get the state for the key that scheduled the timer
        ResultData result = state.value();

        out.collect(result);

        // reset the window state
        state.clear();
    }
}