Apache flink MapState不使用Flink java中的EventTimeSessionWindows存储上一个会话
我需要将上一个会话与同一用户不同会话的平均值进行比较。我使用MapState保留上一个会话,但不知何故MapState从不包含任何上一个键,因此每个会话都是新的。这是我的密码: SessionIdentificationProcessFunction(这是一个收集属于同一会话的所有事件的函数Apache flink MapState不使用Flink java中的EventTimeSessionWindows存储上一个会话,apache-flink,flink-streaming,flink-cep,Apache Flink,Flink Streaming,Flink Cep,我需要将上一个会话与同一用户不同会话的平均值进行比较。我使用MapState保留上一个会话,但不知何故MapState从不包含任何上一个键,因此每个会话都是新的。这是我的密码: SessionIdentificationProcessFunction(这是一个收集属于同一会话的所有事件的函数 static SingleOutputStreamOperator<SessionEvent> sessionUser(KeyedStream<Event, String> stre
static SingleOutputStreamOperator<SessionEvent> sessionUser(KeyedStream<Event, String> stream) {
return stream.window(EventTimeSessionWindows.withGap(Time.minutes(PropertyFileReader.getGAP_SECTION())))
.allowedLateness(Time.minutes(PropertyFileReader.getLATENCY_ALLOWED()))
.process(new SessionIdentificationProcessFunction<Event, SessionEvent, String, TimeWindow>() {
@Override
public void open(Configuration parameters) {
/*state configured to live just one day to avoid garbage accumulation*/
StateTtlConfig ttlConfig = StateTtlConfig
.newBuilder(org.apache.flink.api.common.time.Time.days(1))
.cleanupFullSnapshot()
.build();
MapStateDescriptor<String, SessionEvent> map_descriptor = new MapStateDescriptor<>("prevMapUserSession", String.class, SessionEvent.class);
map_descriptor.enableTimeToLive(ttlConfig);
previous_user_sessions_state = getRuntimeContext().getMapState(map_descriptor);
}
@Override
public SessionEvent generateSessionRecord(String s, Context context, Iterable<Event> elements) {
Comparator<Event> sortFunc = (o1, o2) -> ((o1.timestamp.before(o2.timestamp)) ? 0 : 1);
Event start = StreamSupport.stream(elements.spliterator(), false).max(sortFunc).orElse(new Event());
Event end = StreamSupport.stream(elements.spliterator(), false).max(sortFunc).orElse(new Event());
SessionEvent session_user = (end.timestamp.equals(Timestamp.from(Instant.EPOCH))) ? new SessionEvent(start) : new SessionEvent(end);
session_user.sessionEvents = StreamSupport.stream(elements.spliterator(), false).count();
session_user.sessionDuration = sd;
try {
if (previous_user_sessions_state.contains(s)) {
SessionEvent previous = previous_user_sessions_state.get(s);
/*Update values of the session with the values of the previous which never exist and delete the previous session in the map to create a new entry with the new values updated*/
previous_user_sessions_state.remove(s);
} else {
/*always get here and create a new session*/
}
previous_user_sessions_state.put(s, session_user);
} catch (Exception e) {
e.printStackTrace();
}
return session_user;
}
})
.name("User Sessions");
}
静态SingleOutputStreamOperator会话用户(KeyedStream){
返回stream.window(EventTimeSessionWindows.withGap(Time.minutes(PropertyFileReader.getGAP_SECTION()))
.AllowedLatency(Time.minutes(PropertyFileReader.getLATENCY_ALLOWED()))
.process(新的SessionIdentificationProcessFunction(){
@凌驾
公共无效打开(配置参数){
/*配置为只活一天以避免垃圾累积的状态*/
StateTtlConfig ttlConfig=StateTtlConfig
.newBuilder(org.apache.flink.api.common.time.time.days(1))
.cleanupfullshopshot()
.build();
MapStateDescriptor map_descriptor=新的MapStateDescriptor(“prevMapUserSession”,String.class,SessionEvent.class);
map_描述符.enableTimeToLive(ttlConfig);
先前的用户会话状态=getRuntimeContext().getMapState(映射描述符);
}
@凌驾
public SessionEvent generateSessionRecord(字符串s、上下文、Iterable元素){
比较器sortFunc=(o1,o2)->((o1.时间戳.之前(o2.时间戳))?0:1);
Event start=StreamSupport.stream(elements.spliterator(),false).max(sortFunc.orElse(new Event());
Event end=StreamSupport.stream(elements.spliterator(),false).max(sortFunc.orElse(new Event());
SessionEvent session_user=(end.timestamp.equals(timestamp.from(Instant.EPOCH))?新SessionEvent(start):新SessionEvent(end);
session_user.sessionEvents=StreamSupport.stream(elements.spliterator(),false).count();
session_user.sessionDuration=sd;
试一试{
if(以前的用户会话状态包含){
SessionEvent previous=先前的用户会话状态。获取;
/*使用从不存在的上一个会话的值更新会话的值,并删除映射中的上一个会话,以使用更新的新值创建新条目*/
以前的用户会话状态。删除;
}否则{
/*始终到达此处并创建新会话*/
}
上一个用户会话状态。put(s,会话用户);
}捕获(例外e){
e、 printStackTrace();
}
用户返回会话;
}
})
.名称(“用户会话”);
}
在没有看到如何实现SessionIdentificationProcessFunction的情况下,我不确定到底出了什么问题,但Flink的会话窗口非常特殊,因此这不起作用并不令人感到奇怪。部分问题是,任何给定的会话窗口在与另一个会话窗口合并之前都有很短的生命周期她的会话窗口。(当每个新事件到达时,它最初被分配到自己的会话窗口,然后处理所有当前会话窗口集,并执行任何可能的合并(基于会话间隔)。)
我建议不要使用
getRuntimeContext().getMapState()
,而是使用context.globalState().getMapState()
(其中context
是ProcessWindowFunction.context
传递给ProcessWindowFunction
方法的。这个globalState
是一个KeyedStateStore
就是为了这个目的——保持该键的所有窗口实例之间的全局/共享键控状态。没有看到SessionIdentificationProcessFunction
是如何实现的,我不确定到底出了什么问题,但Flink的会话窗口是非常特别,所以这不起作用并不奇怪。部分问题是,任何给定的会话窗口在与另一个会话窗口合并之前都有很短的生存期。(当每个新事件到达时,它最初被分配到自己的会话窗口,然后处理所有当前会话窗口的集合,并执行任何可能的合并(基于会话间隔)。)
我建议不要使用getRuntimeContext().getMapState()
,而是使用context.globalState().getMapState()
(其中context
是ProcessWindowFunction.context
传递给ProcessWindowFunction
方法的。这个globalState
是一个KeyedStateStore
就是为了这个目的——保持该键的所有窗口实例之间的全局/共享键控状态。非常感谢您的回答,我添加了另一个问题,见上文。我缺少什么?再次非常感谢。请不要使用答案来扩展您的问题上。您应该编辑/扩展原始问题,或者创建一个全新的问题。您可以为要存储在globalState中的MapState创建一次状态描述符(打开),然后在每次调用过程中使用它访问状态。非常感谢您的回答,我添加了另一个问题,请参阅上文。我是什么issing?再次非常感谢。请不要使用答案来扩展您的问题。您应该编辑/扩展y