实时预警需求分析

实时预警需求分析

实时预警,是一种经常出现在实时计算中的业务类型。根据日志数据中系统报错异常,或者用户行为异常的检测,产生对应预警日志。预警日志通过图形化界面的展示,可以提醒监控方,需要及时核查问题,并采取应对措施。

一、需求说明

需求:同一设备,5分钟内三次及以上用不同账号登录并领取优惠劵,并且过程中没有浏览商品。达到以上要求则产生一条预警日志。并且同一设备,每分钟只记录一次预警。

预警日志格式
在这里插入图片描述

二、整体流程设计

框架流程
在这里插入图片描述

开发思路

  1. 从kafka中消费数据,根据条件进行过滤筛选,生成预警日志;
  2. 预警日志保存到ElasticSearch中;
  3. 利用Kibana快速搭建可视化图形界面。

三、实时计算模块

筛选条件分析

  • 同一设备(分组)
  • 5分钟内(窗口)
  • 三次不同账号登录(用户去重)
  • 领取优惠券(行为)
  • 没有浏览商品(行为)
  • 同一设备每分钟只记录一次预警(ES去重)

数据处理流程图
在这里插入图片描述

四、代码开发

object AlterApp {
  /**
   *    分析预警需求:
   *
   *      同一设备,5分钟内三次及以上用不同账号登录并领取优惠劵,并且过程中没有浏览商品。
   *      达到以上要求则产生一条预警日志。并且同一设备,每分钟只记录一次预警
   *
   *       同一设备,在5分钟内,用三个及以上不同账号(uid)登录并领取优惠劵,且,在登录后没有浏览商品,
   *       如果符合此要求,则产生一条预警日志。
   *
   *       限制:  同一设备,每分钟只记录一次预警日志!
   *
   *
   *   输入数据: 日志数据中的事件日志。
   *                  核心字段: evid=coupon
   *                  gmall-mocker 模拟
   *
   *   计算过程:
   *                ①读取输入的数据
   *                      gmall-mocker ---> 模拟数据  ----> gmall-logger  ----> kafka的GMALL_EVENTLOG
   *
   *                 ②封装为样例类
   *                      事件日志有几个字段,样例类就怎么设计!
   *                      多来两个字段:  log_hour,log_date用于分时统计!
   *
   *                ③kafka中的一条数据是一个设备,操作的一个事件的记录
   *                    a) 设置窗口为 5min
   *                    b) 分组 ,按照 mid 将这个批次拉取的所有的数据,按照mid进行分组
   *                    c) 记录当前组中,这个设备一共登录了多少个uid
   *                          Set集合,保存不同的uid
   *
   *                          记录uid的前提是,领取了优惠券!判断当前事件是否是一个领取优惠券的事件,如果是,记录uid!
   *
   *                    d) 如果这个uid 浏览了商品  evid=clickItem,此时这个mid,不预警
   *                    e) 产生一条预警日志
   *                          mid:
   *                          uids:   领取优惠券的uid
   *                          itemIds:  优惠券设计的商品id
   *                          events:   这个设备,所有登录的uid,发生过的事件类型
   *                                       除了clickItem以外的四种类型
   *
   *                          ts:  预警日志生成的时间
   *
   *                    f) 同一设备,每分钟只记录一次预警日志!
   *                          同一个设备,如果在一分钟内生成了多条预警日志,es中只保留一条!
   *
   *                          PUT时,只需要保证,一分钟内一个设备,多次PUT记录的id是一致的!
   *                            00:01:01 PUT   /a/b/mid_156_2021-02-20 00:01
   *                            00:01:02 PUT   /a/b/mid_156_2021-02-20 00:01
   *
   *                             00:02:00 PUT   /a/b/mid_156_2021-02-20 00:02
   *
   *                             id如何设计:  mid_分钟
   *   输出数据: 预警日志
   */
  def main(args: Array[String]): Unit = {
  
    val streamingContext: StreamingContext = new StreamingContext("local[*]","AlterApp",Seconds(10))
  
    //1.从kafka获取DS
    val ds: InputDStream[ConsumerRecord[String, String]] = MykafkaUtil.getKafkaStream(GmallConstants.KAFKA_TOPIC_EVENT,streamingContext)
  
    //2.将DS[ConsumerRecord]转换为DS[StartUpLog]
    val ds1= ds.map(record => {
      val log: EventLog = JSON.parseObject(record.value(), classOf[EventLog])
      log
    })
  
    //统计5分钟内,开窗,然后按照mid分组
    val ds2: DStream[(String, Iterable[EventLog])] = ds1.window(Minutes(5))
      .map(log => (log.mid, log))
      .groupByKey()
    
    //对5分钟内数据进行操作
    val ds3: DStream[CouponAlertInfo] = ds2.map {
      //map为一进一出,不符合要求的数据也要返回一个对象
      case (mid, logs) => {
        //判断这个设备是否符合预警条件,如果符合,生成预警日志
        val uids: util.HashSet[String] = new util.HashSet[String]()
        val itemIds: util.HashSet[String] = new util.HashSet[String]()
        val events: util.ArrayList[String] = new util.ArrayList[String]()
      
        //提供一个是否需要预警的标记,如果点击了商品,不需要预警
        var if_clickProduct = false
      
        //记录这个设备产生的事件
        breakable {
          logs.foreach(log => {
            events.add(log.evid)
            //根据日志类型,是否点击商品,判断是否领取了优惠券
            if (log.evid.equals("clickItem")) {
              if_clickProduct = true
              //终止循环
              break
            }
          
            if (log.evid.equals("coupon")) {
              //将领取优惠券的uid记录
              uids.add(log.uid)
              //记录优惠券关联的商品
              itemIds.add(log.itemid)
            }
          
          })
        }
      
        //遍历完该设备的所有事件,判断该设备是否需要预警
        if (if_clickProduct || uids.size() < 3) {
          null
        } else {
          CouponAlertInfo(mid, uids, itemIds, events, System.currentTimeMillis())
        }
      }
    }
   
    
    //将null值过滤掉
    val ds4: DStream[CouponAlertInfo] = ds3.filter(_!=null)
    
    //打印
    ds4.print(100)
    
    //将结果写入es
    ds4.foreachRDD(rdd=>{
      //以分区为单位写入,节省建立连接的开销
      rdd.foreachPartition(iter=>{
        //每天的预警信息单独存放在一个index
        val indexName = GmallConstants.ES_INDEX_ALERT + LocalDate.now()
        
        val format = new SimpleDateFormat("yyyy-MM-dd HH:mm")
        
        val docList: List[(String, CouponAlertInfo)] = iter.toList.map(info=>(info.mid + "_" + format.format(new Date(info.ts)),info))
        
        MyESUtil.insertBulk(indexName, docList)
        
      })
    })
  
  
    streamingContext.start()
    
    streamingContext.awaitTermination()
  
  }
  

}
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值