Flink自定义触发器提供意外输出

时间:2016-04-22 10:30:20

标签: apache-flink flink-streaming

我想创建一个Trigger,它会在20秒内第一次被触发,之后每五秒就被触发一次。我使用了GlobalWindows和自定义Trigger

val windowedStream = valueStream
                          .keyBy(0)
                          .window(GlobalWindows.create())
                          .trigger(TradeTrigger.of())

以下是TradeTrigger中的代码:

@PublicEvolving
public class TradeTrigger<W extends Window> extends Trigger<Object, W> {

    private static final long serialVersionUID = 1L;

    static boolean flag=false;
    static long ctime = System.currentTimeMillis();

    private TradeTrigger() {
    }

    @Override
    public TriggerResult onElement(
            Object arg0,
            long arg1,
            W arg2,
            org.apache.flink.streaming.api.windowing.triggers.Trigger.TriggerContext arg3)
            throws Exception {
        // TODO Auto-generated method stub

        if(flag == false){
            if((System.currentTimeMillis()-ctime) >= 20000){
               flag = true;
               ctime = System.currentTimeMillis();
               return TriggerResult.FIRE;
            }
            return TriggerResult.CONTINUE;
        } else {
            if((System.currentTimeMillis()-ctime) >= 5000){
                ctime = System.currentTimeMillis();
                return TriggerResult.FIRE;
            }
            return TriggerResult.CONTINUE;
        }

    }

    @Override
    public TriggerResult onEventTime(
            long arg0,
            W arg1,
            org.apache.flink.streaming.api.windowing.triggers.Trigger.TriggerContext arg2)
            throws Exception {
        // TODO Auto-generated method stub
        return TriggerResult.CONTINUE;
    }

    @Override
    public TriggerResult onProcessingTime(
            long arg0,
            W arg1,
            org.apache.flink.streaming.api.windowing.triggers.Trigger.TriggerContext arg2)
            throws Exception {
        // TODO Auto-generated method stub
        return TriggerResult.CONTINUE;
    }


    public static <W extends Window> TradeTrigger<W> of() {
        return new TradeTrigger<>();
    }

}

基本上,当flagfalse时,即第一次,Trigger应在20秒内被解雇并将flag设置为true 。从下一次开始,它应该每5秒钟一次。

我面临的问题是,每次Trigger被触发时,我在输出中只收到一条消息。也就是说,我在20秒后收到一条消息,每五秒钟收到一条消息。 我期待每次触发时输出中有20条消息。

如果我使用.timeWindow(Time.seconds(5))并创建一个五秒的时间窗口,我每5秒就会输出20条消息。 请帮我把这个代码弄好。有什么我想念的吗?

2 个答案:

答案 0 :(得分:4)

您的触发器实施存在一些问题:

  1. 永远不要将函数的状态存储在静态变量中。 Flink不会隔离JVM中的用户进程。相反,它每个TaskManager使用一个JVM并启动多个线程。因此,您的静态布尔标志在多个触发器实例之间共享。您应该存储可从ValueState访问的标志Flink的TriggerContext接口。 Flink将注意检查您的状态并在发生故障时将其恢复。

  2. Trigger.onEvent()仅在新事件到来时调用。因此它不能用于在特定时间触发Window计算。相反,您应该注册事件时间计时器或处理时间计时器(再次通过TriggerContext)。计时器将分别调用Trigger.onEventTime()Trigger.onProcessingTime()。是否使用事件或处理时间取决于您的使用案例。

答案 1 :(得分:1)

在Fabian和Flink邮件列表的答案帮助下工作。 通过ValueState将状态存储在TriggerContext变量中。检查onEvent()方法中的变量,如果是第一次,则注册processingTimeTimer超过当前时间20秒并更新状态。在onProcessingTime方法中,注册了另一个ProcessingTimeTimer超过当前时间5秒,更新了状态并解除了Window