day9:预警案例【用户恶意登陆】【船舶故意超速】【用户行为pv变更buy判断】

文章介绍了使用ApacheFlink流处理框架实现的三个示例,包括检测恶意登录、AIS船速超速报警以及用户行为转变的购买行为识别。通过KeyedProcessFunction和状态变量,实现实时监控并触发相应警告。
摘要由CSDN通过智能技术生成

本文用到的数据请自取:
链接:https://pan.baidu.com/s/1CMnDAj4ga4wsvVw-y83BwQ?pwd=op0g 
提取码:op0g

案例1:如果用户在2s内连续2次登录失败,我们就判定为恶意登录,发出警告

步骤:
1、读文件、取字段、封装样例类 =》
2、分组(user),KeyedProcessFunction =》
3、继承,状态变量1个:存上次失败的数据
4、先判断是不是登录失败了,如果是就再判断状态变量是不是为空,不为空时判断两次失败是不是在2s内。

代码逻辑:

object LoginWarn {
  def main(args: Array[String]): Unit = {
    val env = StreamExecutionEnvironment.getExecutionEnvironment
    env.setParallelism(1)
    //读文件
    val value = env.readTextFile("data/LoginLog.csv")

    //取字段
    value.map(x=>{
      val strings: Array[String] = x.split(",")
      //封装样例类
      Login(strings(0),strings(1),strings(2),strings(3).toLong)
    })
      //分组
      .keyBy(_.userId)
      .process(new login_Warn)
      .print()

    env.execute()
  }
}
class login_Warn extends KeyedProcessFunction [String,Login,String]{
  //定义一个状态变量,存上一次失败的数据
  lazy val last_fail: ValueState[Login] = getRuntimeContext
    .getState(new ValueStateDescriptor[Login]("last_fail", classOf[Login]))
  override def processElement(i: Login,
                              context: KeyedProcessFunction[String, Login, String]#Context,
                              collector: Collector[String]): Unit = {
    //判断进来的数据是fail还是success
    if(i.state == "fail"){
          //先判断状态变量里面有没有值,没值,是第一条fail数据
          if(last_fail.value() == null){
              //为空,先存为状态变量
              last_fail.update(i)
          }else{
                //不为空,是连续的fail数据,就判断两次失败是不是在 2s 内
                if(i.time - last_fail.value().time<2){
                  //输出预警信息
                  collector.collect(s"${i.userId}用户在" +
                    s"${new Timestamp(last_fail.value().time*1000)}和" +
                    s"${new Timestamp(i.time*1000)}之间连续2次登陆失败,锁定账号")
                  //输出之后清空状态变量,开始下一轮判断
                  last_fail.update(i)
                }else{
                  //更新状态变量
                  last_fail.update(i)
                }
          }
      //数据是success,不满足连续两次是fail,清空状态变量
    }else{
      last_fail.clear()
    }

  }
}

***样例类***

//网页登陆样例类
case class Login(userId:String,ip:String,state:String,time:Long)

案例2:如果船在20s以上,2分钟以内连续两次速度超过20,判定故意超速,输出报警信息

步骤:
1、读文件、过滤首行 =》
2、将时间格式转换为时间戳(new SimpleDateFormat()里的parse方法 =》
3、封装样例类 =》
4、分组
5、定义一个状态变量,存上一超速数据 =》
6、判断进来的数据是否超速,如果是就再判断状态变量是不是为空,不为空时判断两次超速是不是在20s以上,2分钟以内。

object AIS_Speed {
  def main(args: Array[String]): Unit = {
    val env = StreamExecutionEnvironment.getExecutionEnvironment
    env.setParallelism(1)
    //读文件
    val value = env.readTextFile("data/ship_trajectory.csv")

    value
      .filter(!_.contains("mmsi"))
      .map(x => {
        val strings: Array[String] = x.split(",")
        val format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS")
        val date: Date = format.parse(strings(1))
        //getTime得到的时间戳是以毫秒为单位,所以要除以1000,变成秒。这里不用除是因为时间间隔太小要精确到毫秒计算。
        val time: Long = date.getTime

        aisCase(strings(0), time, strings(2), strings(3),
          strings(4).toDouble, strings(5), strings(6))
      })
      .keyBy(_.mmsi)
      .process(new aisSpeed_Warn(20))
      .print()
    env.execute()

  }
}
class aisSpeed_Warn(x:Double) extends KeyedProcessFunction [String,aisCase,String]{
  //定义一个状态变量,存上一次超速的数据
  lazy val last_ais: ValueState[aisCase] = getRuntimeContext
    .getState(new ValueStateDescriptor[aisCase]("last_ais", classOf[aisCase]))
  override def processElement(i: aisCase,
                              context: KeyedProcessFunction[String, aisCase, String]#Context,
                              collector: Collector[String]): Unit = {
    //判断进来的数据是否超速
    if(i.speed > x){
      //先判断状态变量里面有没有值,即判断之前有没有速度大于10的记录
          if(last_ais.value() == null){
                //为空,更新状态变量
                last_ais.update(i)
          }else{
                //不为空,即已经有超速记录,就判断两次超速是不是在 10s 内
                if((i.time - last_ais.value().time > 20000) & (i.time-last_ais.value().time)< 120000){
                  //输出预警信息
                  collector.collect(s"${i.mmsi}船" +
                    s"在${last_ais.value().time}速度为${last_ais.value().speed}," +
                    s"在${i.time}速度为${i.speed},判断故意超速,发出警报")
                  //输出之后清空状态变量,开始下一轮判断
                  last_ais.update(i)
                }else{
                  //更新状态变量为最新的数据
                  last_ais.update(i)
                }
          }

      //不满足连续两次超速,清空状态变量
    }else{
      last_ais.clear()
    }

  }
}

***样例类***

case class aisCase(mmsi:String,time:Long,lng:String,lat:String,speed:Double,course:String,id1:String)

案例3:如果用户的行为由pv变成buy就代表他购买了商品,则输出信息

步骤:
1、读数据,封装样例类 =》
2、根据(用户id,商品id)分组 =》

3、定义一个状态变量,存上一条用户行为 =》

4、进行行为的判断是否由pv行为变成buy行为:状态变量为空时更新状态变量,当新的数据是buy,前一条状态是pv时,输出提示信息,否则只更新状态变量

object BuyWarn {
  def main(args: Array[String]): Unit = {
    val env = StreamExecutionEnvironment.getExecutionEnvironment
    env.setParallelism(1)
    //读文件
    val value = env.readTextFile("data/UserBehavior.csv")
    //取字段
    value.map(x=>{
      val strings: Array[String] = x.split(",")
      //封装样例类
      Goods(strings(0),strings(1),strings(2),strings(3),strings(4).toLong)
    })
      .keyBy(x=>(x.userId,x.comId))
      .process(new userShop)
      .print()
    env.execute()
  }
}
class userShop  extends KeyedProcessFunction[(String,String),Goods,String]{
  //定义一个状态变量,存上一条用户行为
  lazy val last_user: ValueState[Goods] = getRuntimeContext
    .getState(new ValueStateDescriptor[Goods]("last_user", classOf[Goods]))
  override def processElement(i: Goods,
                              context: KeyedProcessFunction[(String,String), Goods, String]#Context,
                              collector: Collector[String]): Unit = {
    //先判断状态变量中有没有值
    if(last_user.value() == null){
      //不管来的是什么数据,都更新状态
      last_user.update(i)
    }
    if(i.state == "buy" && last_user.value().state == "pv"){
      //新的数据是buy,前一条状态是pv,才输出提示信息
      collector.collect(s"${i.userId}用户购买了${i.comId}商品,交易成功,具体信息为${last_user.value()},${i}")
    }else{
      last_user.update(i)
    }
  }
}

***样例类***

//用户的行为样例类
case class Goods(userId:String,comId:String,cat:String,state:String,time:Long)

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值