【发布时间】:2021-01-07 12:29:10
【问题描述】:
我有点难以理解 Flink 触发器的工作原理。我的数据流包含带有我基于该 sessionId 聚合的 sessionId 的事件。每个会话将包含一个 Started 和 Ended 事件,但有时 Ended 事件会丢失。
为了处理这个问题,我设置了一个触发器,它会在处理结束事件时发出聚合会话。但是,如果 2 分钟内没有事件从该会话到达,我想发出到目前为止我们聚合的任何内容(我们发送事件的应用程序每分钟发送一次心跳,所以如果我们没有收到任何事件,则认为会话丢失) .
我设置了如下触发函数:
public class EventTimeProcessingTimeTrigger extends Trigger<HashMap, TimeWindow> {
private final long sessionTimeout;
private long lastSetTimer;
// Max session length set to 1 day
public static final long MAX_SESSION_LENGTH = 1000l * 86400l;
// End session events
private static ImmutableSet<String> endSession = ImmutableSet.<String>builder()
.add("Playback.Aborted")
.add("Playback.Completed")
.add("Playback.Error")
.add("Playback.StartAirplay")
.add("Playback.StartCasting")
.build();
public EventTimeProcessingTimeTrigger(long sessionTimeout) {
this.sessionTimeout = sessionTimeout;
}
@Override
public TriggerResult onElement(HashMap element, long timestamp, TimeWindow window, TriggerContext ctx) throws Exception {
lastSetTimer = ctx.getCurrentProcessingTime() + sessionTimeout;
ctx.registerProcessingTimeTimer(lastSetTimer);
if(endSession.contains(element.get(Field.EVENT_TYPE))) {
return TriggerResult.FIRE_AND_PURGE;
}
return TriggerResult.CONTINUE;
}
@Override
public TriggerResult onProcessingTime(long time, TimeWindow window, TriggerContext ctx) throws Exception {
return TriggerResult.FIRE_AND_PURGE;
}
@Override
public TriggerResult onEventTime(long time, TimeWindow window, TriggerContext ctx) throws Exception {
return time == window.maxTimestamp() ?
TriggerResult.FIRE_AND_PURGE :
TriggerResult.CONTINUE;
}
@Override
public void clear(TimeWindow window, TriggerContext ctx) throws Exception {
ctx.deleteProcessingTimeTimer(lastSetTimer);
}
@Override
public boolean canMerge() {
return true;
}
@Override
public void onMerge(TimeWindow window,
OnMergeContext ctx) {
ctx.registerProcessingTimeTimer(ctx.getCurrentProcessingTime() + sessionTimeout);
}
}
为了给事件设置水印,我使用应用程序设置的水印,因为 appEventTime 可能与服务器上的 wallClock 不同。我像这样提取水印:
DataStream<HashMap> playerEvents = env
.addSource(kafkaConsumerEvents, "playerEvents(Kafka)")
.name("Read player events from Kafka")
.uid("Read player events from Kafka")
.map(json -> DECODER.decode(json, TypeToken.of(HashMap.class))).returns(HashMap.class)
.name("Map Json to HashMap")
.uid("Map Json to HashMap")
.assignTimestampsAndWatermarks(new BoundedOutOfOrdernessTimestampExtractor<HashMap>(org.apache.flink.streaming.api.windowing.time.Time.seconds(30))
{
@Override
public long extractTimestamp(HashMap element)
{
long timestamp = 0L;
Object timestampAsObject = (Object) element.get("CanonicalTime");
timestamp = (long)timestampAsObject;
return timestamp;
}
})
.name("Add CanonicalTime as timestamp")
.uid("Add CanonicalTime as timestamp");
现在我觉得奇怪的是,当我在调试中运行代码并在 Trigger 的 clear 函数中设置断点时,它会不断被调用。即使在触发器中没有达到 FIRE_AND_PURGE 点。所以感觉就像我完全误解了触发器应该如何工作。而且我的实现根本没有做我认为它正在做的事情。
我想我的问题是,触发器什么时候应该调用 clear ?这是实现组合 EventTimeTrigger 和 ProcessingTimeTrigger 的正确方法吗?
感谢我能得到的所有帮助。
更新 1:(2020-05-29)
为了提供更多关于如何设置的信息。 我的环境设置如下:
final StreamExecutionEnvironment env = StreamExecutionEnvironment.getExecutionEnvironment();
env.setRestartStrategy(RestartStrategies.failureRateRestart(60, Time.of(60, TimeUnit.MINUTES), Time.of(60, TimeUnit.SECONDS)));
env.enableCheckpointing(5000);
env.getCheckpointConfig().setMinPauseBetweenCheckpoints(2000);
env.getCheckpointConfig().setCheckpointingMode(CheckpointingMode.EXACTLY_ONCE);
env.setStreamTimeCharacteristic(TimeCharacteristic.EventTime);
所以我对整个流使用 EventTime。 然后我像这样创建窗口:
DataStream<PlayerSession> playerSessions = sideEvents
.keyBy((KeySelector<HashMap, String>) event -> (String) event.get(Field.SESSION_ID))
.window(ProcessingTimeSessionWindows.withGap(org.apache.flink.streaming.api.windowing.time.Time.minutes(5)))
.trigger(new EventTimeProcessingTimeTrigger(SESSION_TIMEOUT))
.aggregate(new SessionAggregator())
.name("Aggregate events into sessions")
.uid("Aggregate events into sessions");
【问题讨论】:
-
了解更多有关如何使用触发器的上下文会很有帮助——我想看看您是否正在设置时间特性,这是一个键控窗口还是一个窗口,如何窗口分配器被构造,等等。
-
这些是什么类型的窗口——你使用的是 Flink 的会话窗口吗?
-
@DavidAnderson 感谢您的浏览。我更新了原始帖子,提供了有关如何设置流以及如何使用 Windows 的更多信息。
标签: java apache-flink flink-streaming