我有以下用例。
有一台机器正在向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);
}
这是对一个流数据执行多种模式的正确方法,还是有优化的方法来实现这一目标。通过上述方法,我们遇到了PartitionNotFoundException
和UnknownTaskExecutorException
以及内存问题。
答案 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);