项目说明
日志收集模块
- 运行gmall0311-logger项目下的Gmall0311LoggerApplication,启动web服务收集上传过来的日志并存进kafka中
- 运行gmall0311-mock项目下的JsonMocker,模拟app应用上传日志到web端
- 查看kafka,可以看到数据已保存到kafka
实时预警
根据日志数据中的系统报错异常,或者用户行为异常检测,产生预警日志并图形化展示
需求:同一设备,5分钟内三次及以上用不同账号登录并领取优惠劵,并且在登录到领劵过程中没有浏览商品。达到以上要求则产生一条预警日志。
val sparkConf: SparkConf = new SparkConf().setAppName("alert_app").setMaster("local[*]")
val ssc =new StreamingContext(sparkConf,Seconds(5))
val inputDstream: InputDStream[ConsumerRecord[String, String]] = MyKafkaUtil.getKafkaStream(GmallConstants.KAFKA_TOPIC_EVENT,ssc)
val eventInfoDstream: DStream[EventInfo] = inputDstream.map { record =>
val eventInfo: EventInfo = JSON.parseObject(record.value(), classOf[EventInfo])
eventInfo
}
eventInfoDstream.cache()
// 1 ) 5分钟内 --> 窗口大小 window 窗口 (窗口大小,滑动步长 ) 窗口大小 数据的统计范围 滑动步长 统计频率
val eventWindowDStream: DStream[EventInfo] = eventInfoDstream.window(Seconds(300),Seconds(5))
// 2) 同一设备 groupby mid
val groupbyMidDstream: DStream[(String, Iterable[EventInfo])] = eventWindowDStream.map(eventInfo=>(eventInfo.mid,eventInfo)).groupByKey()
// 3 ) 用三次及以上不同账号登录并领取优惠劵 没有 浏览商品
// map 变换结构 (预警结构) 经过判断 把是否满足预警条件的mid 打上标签
val checkedDstream: DStream[(Boolean, AlertInfo)] = groupbyMidDstream.map { case (mid, eventInfoItr) =>
val couponUidSet = new util.HashSet[String]()
val itemsSet = new util.HashSet[String]()
val eventList = new util.ArrayList[String]()
var hasClickItem = false
breakable(
for (eventInfo: EventInfo <- eventInfoItr) {
eventList.add(eventInfo.evid) //收集mid的所有操作事件
if (eventInfo.evid == "coupon") {
//点击购物券时 涉及登录账号
couponUidSet.add(eventInfo.uid)
itemsSet.add(eventInfo.itemid) //收集领取购物券的商品
}
if (eventInfo.evid == "clickItem") { //点击商品
hasClickItem = true
break() //如果有点击 直接退出
}
}
)
//判断 符合预警的条件 1) 点击购物券时 涉及登录账号 >=3 2) events not contain clickItem
(couponUidSet.size >= 3 && !hasClickItem, AlertInfo(mid, couponUidSet, itemsSet, eventList, System.currentTimeMillis())) //(是否符合条件 ,日志信息)
}
val alterDstream: DStream[AlertInfo] = checkedDstream.filter(_._1).map(_._2)
// 保存到ES中
......
采集架构图
spark streaming实时统计日志中的信息并输出到es中,最终由kibana展示
实时计算
T+1模式
- 利用sqoop从业务数据库中批量抽取数据
- 利用数仓作业,在dws层组织宽表(用户购买行为)
- 开发spark的批处理任务,把dws层的宽表导入es中
- 从es中读取数据并显示到可视化界面
优点是能利用离线处理好的dws层宽表,直接导出一份到es进行快速交互的分析,但时效性等同于离线数据
T+0模式
- 利用canal抓取对应数据表的实时新增变化数据,推送到kafka
- 在spark-streaming中进行转换、过滤,关联组合成宽表的结构
- 保存到es中,读取es数据并展示到可视化界面中
此时会产生双流join
双流join即订单的数据来了,但订单项的数据还没过来,或者订单项数据过来了,但订单表的数据没过来。两者之间无法直接关联双流join的解决方案:如果另一方数据没有过来,则缓存这一方的数据,查询的时候如果stream里面没有相应的数据,就继续查询缓存里面是否有匹配的数据
canal:分布式数据同步中间件
canal是基于数据库增量日志解析,提供增量数据订阅和消费场景1:更新缓存
场景2:抓取业务数据新增变化表,用于制作拉链表
场景3:抓取业务数据新增变化数据,用于制作实时统计
phoniex是hbase的开源sql皮肤,可使用jdbc api开代替hbase客户端api来创建表、插入数据和查询hbase
本项目中sparkstreaming从kafka中拉取数据保存到hbase中都使用了phoniex,便于后面直接使用sql语句来统计查询