【Flink】CEP

一、前言

CEP——Complex Event Processing,复制事件处理,Flink CEP是在Flink中复杂事件处理库。处理事件的规则叫做Pattern,Flink CEP 提供了API,用于对输入流数据进行复制事件规则定义,用来提取符合规则的事件序列。Pattern API 大致分为三种:个体模式,组合模式,模式组

Flink CEP的应用场景:

  • 实时监控:访问日志中用脚本或工具暴力登陆的用户,发现活跃用户等
  • 风险控制:识别危险交易和非法交易
  • 营销广告:跟踪用户行为制定对应的推广策略

二、 Pattern API

1、个体模式

组成复杂规则的每一个单独的模式定义。个体模式包括单例模式和循环模式,单例模式只接收一个事件,循环模式可以接收多个事件。

量词

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

start.time(4) // 匹配出现4次
start.time(4).optional // 匹配出现0次或4次
start.time(2,4) // 匹配出现2,3,4次
start.time(2,4).greedy //匹配出现2,3,4次,尽可能多地重复匹配
start.oneOrMore // 匹配出现1或多次
start.timeOrMore(2).optional.greedy // 匹配出现0,2或多次,尽可能多地重复匹配

条件

每个模式都需要指定触发条件,作为模式是否接受事件进入的判断依据。

  1. 简单条件
start.where(event=>event.getName.startsWith("foo"))
  1. 组合条件
start.where(event=>.../*some condition */).or(event=> /*or condition*/)
  1. 终止条件 如果使用了oneOrMore或者oneOrMore.optional,建议使用.until()作为终止条件,以便清理状态。
  2. 迭代条件 能够对模式之前所有接收的事件进行处理;调用.where((value,ctx) => {…}),可以调用ctx.getEventForPattern(“name”)

2、组合模式

很多个体模式组合起来,就形成了整个组合模式,又叫模式序列。

.next()  // 严格近邻  (a,b,c,d) -> a next b
.followedBy() // 宽松近邻  (a,b,c,d) -> a followedBy c
.followedByAny() // 非确定新宽松近邻(之前已经匹配过的事件可以再次使用) (a,b,c,d) -> a followedByAny c, a followedByAny d
.notNext()
.notFollowedBy()
  1. 所有模式序列必须以 .begin() 开始
  2. 模式序列不能以 .notFollowedBy() 结束
  3. not类型模式不能被optional修饰
  4. 可以为模式指定时间约束,用来要求在多长时间内匹配有效 next.with(Time.seconds(10))

3、模式组

将一个组合模式作为条件嵌套在个体模式里,成为一组模式。

4、模式检测

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

5、匹配事件的提取

创建PatternStream后,可以用于select或者flatSelect方法,从检测到的事件序列中提取事件了。

6、超时事件的提取

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

案例

Flink CEP 开发流程:

  1. DateSource 中数据转换为Datetream
  2. 定义Pattern,并将DateStream和Pattern组合转换为PatternStream
  3. PatternStream经过select、process等算子转换为DateStream
  4. 再次双簧的DateStream经过处理后,sink到目标库
<!-- pom.xml 中需引入的依赖:-->
<dependency>
    <groupId>org.apache.flink</groupId>
    <artifactId>flink-cep_2.12</artifactId>
    <version>1.11.1</version>
</dependency>
public static void main(String[] args) throws Exception {
	StreamExecutionEnvironment env = StreamExecutionEnvironment.getExecutionEnvironment();
	env.setStreamTimeCharacteristic(TimeCharacteristic.EventTime);
	env.setParallelism(1);
   // 数据源
    DataStreamSource<RawLogGroupList> ds = env.addSource(../* TrackLog 类型数据源 */..);
    KeyedStream<TrackLog, String> keyedStream = ds
    .filter(value -> value.getPorjectId().equals("2") && !value.getLib().equals("JS"))
    .assignTimestampsAndWatermarks(new WatermarkStrategy<TrackLog>() {
        @Override
        public WatermarkGenerator<TrackLog> createWatermarkGenerator(WatermarkGeneratorSupplier.Context context) {
            return new WatermarkGenerator<TrackLog>() {
                long maxTimeStamp = Long.MIN_VALUE;
                @Override
                public void onEvent(TrackLog event, long eventTimestamp, WatermarkOutput output) {
                    maxTimeStamp = Math.max(maxTimeStamp, event.getServerTime());
                }

                long maxOutOfOrderness = 5000L;
                @Override
                public void onPeriodicEmit(WatermarkOutput output) {
                    output.emitWatermark(new Watermark(maxTimeStamp - maxOutOfOrderness));
                }
            };
        }
    }.withTimestampAssigner((value, recordTimestamp) -> value.getServerTime())) // 在数据源上做出watermark
    .keyBy(value -> value.getId());  // 在watermark上分组

    // 创建模式pattern
    Pattern<TrackLog, TrackLog> pattern = Pattern.<TrackLog>begin("start").where(new IterativeCondition<TrackLog>() {
        @Override
        public boolean filter(TrackLog value, Context<TrackLog> ctx) throws Exception {
            return value.getEvent().equals("AppLeaveScreen");
        }
    }).next("next").where(new IterativeCondition<TrackLog>() {
        @Override
        public boolean filter(TrackLog value, Context<TrackLog> ctx) throws Exception {
            return value.getEvent().equals("AppViewScreen");
        }
    }).within(Time.seconds(10));

    // 在数据流上进行模式匹配
    PatternStream<TrackLog> patternStream = CEP.pattern(keyedStream, pattern);

    // 提取匹配成功的数据
    patternStream.process(new PatternProcessFunction<TrackLog, String>() {
        @Override
        public void processMatch(Map<String, List<TrackLog>> map, Context context, Collector<String> out) throws Exception {
            out.collect("lib: " +map.get("next").get(0).getLib()+" id: " +map.get("next").get(0).getId());
        }
    })
    .print();

    env.execute("add candidate demo");
 }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值