我使用Flink Stream处理3G网络中的数据流量日志(GPRS隧道协议)。而且我在用户的用户会话中合成信息时遇到了麻烦。
例如:如何映射一个会话的开始和结束。我不知道Flink流媒体是否适合处理这样的复杂协议?
P / S:
我们捕获3G网络中SGSN和GGSN之间的数据交换(使用GTP协议和GTP-C / U消息)。当SGSN发送 CreateReq(TEID,Seq,IMSI,TEID_dl,TEID_data_dl)消息和GGSN响应 CreateRsp(TEID_dl,Seq,TEID_ul,TEID_data_ul)消息时,会话开始。
在会话建立之后,从SGSN发送到GGSN的其他GTP-C消息(例如:UpdateReq,DeleteReq)使用TEID_ul并且响应消息使用TEID_dl,GTP-U消息使用TEID_data_ul(SGSN - > GGSN)和TEID_data_dl(GGSN - > ; SGSN)。 GTP-U消息包含AppID(facebook,twitter,web),url,...
等信息
最后,我想处理连续日志数据流并映射同一用户(IMSI)的GTP-C消息和GTP-U以进行报告。
我试过这个:
val sessions = createReqs.connect(createRsps).flatMap(new CoFlatMapFunction[CreateReq, CreateRsp, Session] {
// holds CreateReqs indexed by (tedid_dl,seq)
private val createReqs = mutable.HashMap.empty[(String, String), CreateReq]
// holds CreateRsps indexed by (tedid,seq)
private val createRsps = mutable.HashMap.empty[(String, String), CreateRsp]
override def flatMap1(req: CreateReq, out: Collector[Session]): Unit = {
val key = (req.teid_dl, req.header.seqNum)
val oRsp = createRsps.get(key)
if (!oRsp.isEmpty) {
val rsp = oRsp.get
println("OK")
out.collect(new Session(rsp.header.time, req.imsi, req.teid_dl, req.teid_ddl, rsp.teid_upl, rsp.teid_dupl, req.rat, req.apn))
createRsps.remove(key)
} else {
createReqs.put(key, req)
}
}
override def flatMap2(rsp: CreateRsp, out: Collector[Session]): Unit = {
val key = (rsp.header.teid, rsp.header.seqNum)
val oReq = createReqs.get(key)
if (!oReq.isEmpty) {
val req = oReq.get
out.collect(new Session(rsp.header.time, req.imsi, req.teid_dl, req.teid_ddl, rsp.teid_upl, rsp.teid_dupl, req.rat, req.apn))
createReqs.remove(key)
} else {
createRsps.put(key, rsp)
}
}
}).print()
此代码始终返回空结果。输入流包含同一会话的CreateRsp和CreateReq消息的事实。它们看起来非常接近(1秒内)。当我调试时,每次都有 oReq.isEmpty == true 。
我做错了什么?
答案 0 :(得分:0)
说实话,通过这里的电信公司细节来看有点困难,但如果我理解正确你至少有3个流,前两个是 CreateReq 和 CreateRsp 流。
为了检测会话的建立,我将使用 ConnectedDataStream 抽象来共享上述两个流之间的状态。查看此example的使用情况或相关的Flink docs。
这是你想要实现的目标吗?