如何在Apache Flink中为会话窗口分配ID?

时间:2019-06-13 15:20:03

标签: apache-flink flink-streaming

如何在Apache Flink中为会话窗口分配ID?

最终,我想在会话窗口打开时以一个会话窗口ID一对一地丰富事件(我不想等到窗口关闭后才发出丰富事件)。

我试图使用AggregateFunction来做到这一点,但是我认为merge()并不像我期望的那样工作。它似乎是用于合并窗口,而不是用于合并窗格(触发触发)。在我的管道中似乎从未调用过它。因此,似乎触发器之间没有共享状态!

会话窗口ID将是第一个事件落入窗口的时间戳(由于无保证的排序,这可能意味着某些事件可能会以较早的时间戳落入同一会话窗口中-我很好与此)。

public class FooSessionState {

  private Long sessionCreationTime;

  private FooMatch lastMatch;
}

/**
 * Aggregator that assigns session ids to elements of a session window
 */
public class SessionIdAssigner implements
    AggregateFunction<FooMatch, FooSessionState, FooSessionEvent> {

  static final long serialVersionUID = 0L;

  @Override
  public FooSessionState createAccumulator() {
    return new FooSessionState();
  }

  @Override
  public FooSessionState add(FooMatch value, FooSessionState sessionState) {
    if (sessionState.getSessionCreationTime() == null) {
      sessionState.setSessionCreationTime(value.getReport().getTimestamp());
    }
    sessionState.setLastMatch(value);
    return sessionState;
  }

  @Override
  public FooSessionEvent getResult(FooSessionState accumulator) {
    FooSessionEvent sessionEvent = new FooSessionEvent();
    sessionEvent.setFooMatch(accumulator.getLastMatch());
    sessionEvent.setSessionCreationTime(accumulator.getSessionCreationTime());
    return sessionEvent;

  }

  @Override
  public FooSessionState merge(FooSessionState a, FooSessionState b) {

    if ( a.getSessionCreationTime() != null) {
      b.setSessionCreationTime(a.getSessionCreationTime());
    }

    return b;
  }
}

我的计划是按如下方式使用它:

stream.keyBy(new FooMatchKeySelector())
    .window(EventTimeSessionWindows.withGap(Time.milliseconds(config.getFooSessionWindowTimeout())))
    .trigger(PurgingTrigger.of(CountTrigger.of(1L)))
    .aggregate(new SessionIdAssigner())

1 个答案:

答案 0 :(得分:0)

我认为会话窗口不适合您要实现的目标。它们的设计目的是汇总每个会话的事件,但不能丰富每个事件,即,它们计算结果并在关闭窗口时发出结果。如您所注意到的,会话窗口通过为每个事件创建一个新窗口并合并重叠的窗口来工作。之所以选择这种设计,是因为事件可能会无序到达。因此,可能有两个窗口,以后通过桥接事件将它们连接起来。

我建议使用ProcessFunction来实现逻辑,该逻辑收集事件并将事件按时间戳排序。收到水印后,它将发出具有正确会话ID的所有收集的事件。因此,您仅将两个水印之间的事件保持在状态中。除了这些事件之外,您还需要保留最后发出的事件的时间戳和最后发出的会话ID,以执行正确的会话化。