【flink】flink 复杂事件处理 CEP

@【在这里插入图片描述

1.概述

转载:Flink系列 13. 复杂事件处理 CEP
请到原文查看。。。

1. 什么是 CEP?

  • CEP 是 Flink 中实现的复杂事件处理库,(Complex Event Processing,CEP)是一种基于流处理的技术,CEP是Flink一个基于复杂事件监测处理的库
  • CEP通过一个或多个由简单事件构成的事件流通过一定的规则匹配,然后输出用户想得到的数据,满足规则的复杂事件。
  • CEP复杂事件处理DataStrem API 提供了 FlinkCEP 组件栈,专门用于对复杂事件的处理,帮助用户从流式数据中发掘有价值的信息,主要应用于防范网络欺诈、设备故障检测、风险规避和智能营销等领域

2. CEP 的特点

目标:从有序的简单事件流中发现一些高阶特征

输入:一个或多个简单事件构成的事件流

处理:识别简单事件之间的内在联系,多个符合一定规则的简单事件构成复杂事件

输出:满足规则的复杂事件

在这里插入图片描述

3. Pattern API

  • flinkCEP 提供了 Pattern API,定义用于对输入流数据进行复杂事件的规则,用来提取符合规则的事件结果

  • 处理事件的规则,被叫做“模式(Pattern)”

  • 包含四个步骤

    • 输入事件流的创建

    • Pattern 的定义

    • Pattern 应用在事件流上检测

    • 选取结果

// 定义一个 Pattern 
val pattern = Pattern.begin[event]("start").where(_.getId == 42) 
  .next("middle").subtype(classOf(SubEvent)).where(_.getTemp >= 10.0) 
  .followedBy("end").where(_.getName == "end")

// 将创建好的 Pattern 应用到输入事件流上
val patternStream = CEP.pattern(inputStream.pattern)

// 获取事件序列,得到处理结果
val result:DataStream(alert) = patternStream.select(createAlert(_))

Pattern API 模式有几下几种分类

  • 个体模式(Individual Patterns)

  • 模式序列\组合模式(Combining Patterns )

  • 模式组(Groups of patterns)

    • 将一个模式序列作为条件,嵌到在个体模式里,成为一组模式

3.1 个体模式(Individual Patterns)

个体模式就是组成复杂规则的每个单独的模式定义

个体模式可以包括“单利模式 singleton” 和“循环模式 loogping”

单例模式只接收一个事件,而循环模式可以接收多个事件

start.times(3).where(_.behavior.startWith(“fav”))

3.1.1 模式中的量词(Quantifier)

可以在一个个体模式后追加量词,也就是指定循环次数

// 匹配出现4次
start.times(4)
// 匹配出现 2-4 次
start.times(2,4)
// 匹配出现0次或4次
start.times(4).optional
// 匹配出现 2-4 次,并且尽可能多的重复匹配
start.times(2,4).greedy
// 匹配出现 1 次或多次
start.oneOrMore
// 匹配出现 0 次、两次或多次
start.timesOrMore(2).optional.greedy

3.1.2 个体模式的条件

条件(Condition)

  • 每个模式都需要指定触发的条件,作为模式是否接受事件进入的判断依据
  • CEP 中的个体模式主要通过调用.where() .or() .until()来指定条件

3.1.3 模式条件的分类

  • 简单条件

  • 通过.where()方法对事件中的字段进行判断筛选,决定是否接受该事件

  • start.where(event=>event.getName.startWith(“foo”))

  • 组合条件

    • 将简单条件进行组合:.or() 方法表示逻辑相连,.where() 的直接组合就是 AND
    • pattern.where(event=>…).or(event=>…)
  • 终止条件

    • 如果使用了 oneOrMore 或者 oneOrMore.optional 建议使用.until() 作为终止条件,以便清理状态
  • 迭代条件(Iterative Condition)

    • 能够对模式之前所有接收的事件进行处理
    • 调用.where((value,ctx)=>{…}) 可以调用 ctx.getEventsForPattern(“name”)

3.2 模式序列/组合模式

  • 很多个体模式组合起来,就形成了整个的模式序列
  • 模式序列必须是以一个“初始模式”开始:val start = Pattern.begin(“start”)

3.2.1 严格近邻(Strict Contiguity)

  • 所有事件按照严格的顺序出现,中间没有任何不匹配的事件,由.next()指定
  • 例如对于模式 “a next b “ 事件序列 【a,c,b,d】则没有匹配

在这里插入图片描述

3.2.2 宽松近邻(Relaxed Contiguity)

  • 允许中间出现不匹配的时间,由.followBy()指定
  • 例如对于模式 “a followBy b “ 事件序列 【a,c,b,d】匹配为{a,b}

在这里插入图片描述

3.2.3 非确定性宽松近邻(Non-Deterministic Relaxed Contiguity)

  • 进一步放宽条件,之前已经匹配过得事件也可以再次使用,由.followedByAny()指定
  • 例如对于模式 “a followBy b “ 事件序列 【a,c,b1,b2】匹配为{a,b1},{a,b2}

在这里插入图片描述

除了上述模式之外,还可以定义“不希望出现某种近邻关系”

  • .notNext : 不想让某个事件严格紧邻前一个事件发生
  • .notFollowedBy :不想让某个事件在两个事件之间发生

3.2.4 注意项

  • 所有模式序列必须以.begin()开始
  • 模式序列不能以.notFollowedBy()结束
  • “not”类型的模式不能被 optional所修饰
  • 此外,还可以为模式指定时间约束,用来要求在多长时间内匹配有效 next.within(Time.seconds(10))

3.3 模式的检测

指定要查找的模式序列后,就可以将其应用于输入流以检测潜在匹配
调用 CEP.pattern(),给定输入流和模式,就能得到一个 PatternStream

val input:DataStream[Event] = ...
val pattern:Pattern[Event,_] = ...
val patternStream:PatternStream[Event] = CEP.pattern(input,pattern)

3.3.1 匹配事件的提取

创建 PatternStream 之后,就可以应用 select 或者 flatselect方法,从检测到的事件序列中提取事件了

select()方法需要输入一个 select function作为参数,每个成功匹配的事件序列都会调用它

select() 以一个 Map[String,Iterable[N]] 来接收匹配到的事件序列,其中 key 就是每个模式的名称,而 value 就是所接收到的事件的 Iterable 类型

def selectFn(pattern:Map[String,Iterable[In]]):OUT= {
    
    
  val startEvent = pattern.get("start").get.next
  val endEvent = pattern.get("end").get.next
  OUT(startEvent,endEvent)
}

3.3.2 超时事件提取

当一个模式通过 within关键字定义了检测窗口时间时,部分时间序列可能因为超过窗口长度而被丢弃,为了能够处理这部分超时的数据,select 和 flatSelect API 调用允许指定超时处理程序

超时处理程序会接收到目前为止模式匹配到的所有事件,由一个 OutputTag 定义接收到的额超时事件序列

val patternStream:PatternStream[Event] = CEP.pattern(input,pattern)
val outputTag = OutputTag[String]("side-output")
val result = patternStream.select(outputTag){
    
    
  (pattern:Map[String,Iterable[Event]],timestamp:Long)=>TimeoutEvent()
}{
    
    
  pattern:Map[String,Iterable[Event]] => complexEvent()
}
val timeoutResult:DataStream<TimeoutEvent> = result.getSideoutput(outputTag)

猜你喜欢

转载自blog.csdn.net/qq_21383435/article/details/113994758