在一个流数据上并行处理Flink CEP中的多个模式

时间:2019-05-16 04:59:40

标签: java apache-flink complex-event-processing

我有以下用例。

有一台机器正在向CEP engine接收事件流到Kafka,当流数据满足条件时会生成警告。

FlinkKafkaConsumer011<Event> kafkaSource = new FlinkKafkaConsumer011<Event>(kafkaInputTopic, new EventDeserializationSchema(), properties);
DataStream<Event> eventStream = env.addSource(kafkaSource);

事件POJO包含ID,名称,时间,IP。

机器将向Kafka发送大量数据,并且机器上有35个唯一的事件名称(例如name1,name2 ..... name35),我想检测每种事件名称组合的模式(例如name1与name2共同出现) ,name1与name3 ..等共存)。我总共有1225种组合。

规则POJO包含e1Name和e2Name。

List<Rule> ruleList -> It contains 1225 rules.

for (Rule rule : ruleList) {
    Pattern<Event, ?> warningPattern = Pattern.<Event>begin("start").where(new SimpleCondition<Event>() {

    @Override
        public boolean filter(Event value) throws Exception {
            if(value.getName().equals(rule.getE1Name())) {
                return true;
            }
            return false;
        }

    }).followedBy("next").where(new SimpleCondition<Event>() {
        @Override
        public boolean filter(Event value) throws Exception {
            if(value.getName().equals(rule.getE2Name())) {
                return true;
            }
            return false;
        }
    }).within(Time.seconds(30));
    PatternStream patternStream = CEP.pattern(eventStream, warningPattern);
}

这是对一个流数据执行多种模式的正确方法,还是有优化的方法来实现这一目标。通过上述方法,我们遇到了PartitionNotFoundExceptionUnknownTaskExecutorException以及内存问题。

1 个答案:

答案 0 :(得分:0)

IMO,您不需要实现目标的模式。您可以为源定义一个有状态的映射函数,该函数将事件名称成对映射(最近的两个名称)。之后,将源窗口缩短至30秒,然后将简单的WordCount示例应用于源。

状态映射函数可以是这样的(仅接受事件名称,您需要根据输入内容进行更改-提取事件名称等):

public class TupleMap implements MapFunction<String, Tuple2<String, Integer>>{
    Tuple2<String, String> latestTuple = new Tuple2<String, String>();

    public Tuple2<String, Integer> map(String value) throws Exception {
        this.latestTuple.f0 = this.latestTuple.f1;
        this.latestTuple.f1 = value;
        return new Tuple2<String, Integer>(this.latestTuple.f0 + this.latestTuple.f1, 1);
    }
}

并以如下方式获得事件名称对和结果计数为元组的结果(可能写入了卡夫卡水槽?):

DataStream<Tuple2<String, Integer>> source = stream.map(new TupleMap());
SingleOutputStreamOperator<Tuple2<String, Integer>> sum = source.keyBy(0).timeWindow(Time.seconds(30)).sum(1);