文章目录
本文主要针对 Flink 源码中 flink-cep
模块,带大家跑一下其中的测试类 CEPITCase.java
,可以直观的了解到 flink cep 的功能。
为了方便分析,对源码中的示例会有些许改动,并把代码粘贴在了文中。
1. testSimplePatternCEP
public class CEPITCase extends AbstractTestBase{
/**
* Checks that a certain event sequence is recognized.
* 全局匹配一组先后发生的事件序列
*/
@Test
public void testSimplePatternCEP() throws Exception {
StreamExecutionEnvironment env = StreamExecutionEnvironment.getExecutionEnvironment();
DataStream<Event> input = env.fromElements(
new Event(1, "barfoo", 1.0),
new Event(2, "start", 2.0),
new Event(3, "foobar", 3.0),
new SubEvent(4, "foo", 4.0, 1.0),
new Event(5, "middle", 5.0),
new SubEvent(6, "middle", 6.0, 2.0),
new SubEvent(7, "bar", 3.0, 3.0),
new Event(42, "42", 42.0),
new Event(8, "end", 1.0)
);
// Pattern 组
Pattern<Event, ?> pattern = Pattern.<Event>begin("start").where(new SimpleCondition<Event>() {
@Override
public boolean filter(Event value) throws Exception {
// start Pattern
System.out.println("testSimplePatternCEP start -> " + value + ", " + value.getName().equals("start"));
return value.getName().equals("start");
}
})
// 1. 前一个模式
// 2. 创建一个新的模式
// 3. 模式名
// 4. where 指定模式内容
.followedByAny("middle").subtype(SubEvent.class).where(
new SimpleCondition<SubEvent>() {
@Override
public boolean filter(SubEvent value) throws Exception {
// middle Pattern
// 5. 核心处理逻辑
System.out.println("testSimplePatternCEP middle -> " + value + ", " + value.getName().equals(
"middle"));
return value.getName().equals("middle");
}
}
)
.followedByAny("end").where(new SimpleCondition<Event>() {
@Override
public boolean filter(Event value) throws Exception {
// end Pattern
System.out.println("testSimplePatternCEP end -> " + value + ", " + value.getName().equals("end"));
return value.getName().equals("end");
}
});
// CEP 匹配
PatternStream<Event> patternStream = CEP.pattern(input, pattern);
// 经过 CEP 匹配之后的输出流
DataStream<String> result = patternStream.flatSelect((p, o) -> {
StringBuilder builder = new StringBuilder();
builder.append(p.get("start").get(0).getId()).append(",")
.append(p.get("middle").get(0).getId()).append(",")
.append(p.get("end").get(0).getId());
o.collect(builder.toString());
System.out.println("testSimplePatternCEP -> " + builder.toString());
}, Types.STRING);
List<String> resultList = new ArrayList<>();
DataStreamUtils.collect(result).forEachRemaining(resultList::add);
// 根据设置的 Pattern,返回 id 列表 2,6,8
assertEquals(Arrays.asList("2,6,8"), resultList);
}
}
输出结果,匹配出 <2,6,8> 序列:
testSimplePatternCEP start -> Event(1, barfoo, 1.0), false
testSimplePatternCEP start -> Event(2, start, 2.0), true
testSimplePatternCEP start -> Event(3, foobar, 3.0), false
testSimplePatternCEP middle -> SubEvent(4, foo, 4.0, 1.0), false
testSimplePatternCEP start -> SubEvent(4, foo, 4.0, 1.0), false
testSimplePatternCEP start -> Event(5, middle, 5.0), false
testSimplePatternCEP middle -> SubEvent(6, middle, 6.0, 2.0), true
testSimplePatternCEP start -> SubEvent(6, middle, 6.0, 2.0), false
testSimplePatternCEP end -> SubEvent(7, bar, 3.0, 3.0), false
testSimplePatternCEP middle -> SubEvent(7, bar, 3.0, 3.0), false
testSimplePatternCEP start -> SubEvent(7, bar, 3.0, 3.0), false
testSimplePatternCEP end -> Event(42, 42, 42.0), false
testSimplePatternCEP start -> Event(42, 42, 42.0), false
testSimplePatternCEP end -> Event(8, end, 1.0), true
testSimplePatternCEP start -> Event(8, end, 1.0), false
testSimplePatternCEP -> 2,6,8
2. testSimpleKeyedPatternCEP
public class CEPITCase extends AbstractTestBase {
/**
* 先按照 id 分组,再去匹配各自的 Pattern
*/
@Test
public void testSimpleKeyedPatternCEP() throws Exception {
StreamExecutionEnvironment env = StreamExecutionEnvironment.getExecutionEnvironment();
env.setParallelism(2);
DataStream<Event> input = env.fromElements(
new Event(1, "barfoo", 1.0),
new Event(2, "start", 2.0),
new Event(3, "start", 2.1),
new Event(3, "foobar", 3.0),
new SubEvent(4, "foo", 4.0, 1.0),
new SubEvent(3, "middle", 3.2, 1.0),
new Event(42, "start", 3.1),
new SubEvent(42, "middle", 3.3, 1.2),
new Event(5, "middle", 5.0),
new SubEvent(2, "middle", 6.0, 2.0),
new SubEvent(7, "bar", 3.0, 3.0),
new Event(42, "42", 42.0),
new Event(3, "end", 2.0),
new Event(2, "end", 1.0),
new Event(42, "end", 42.0)
).keyBy(new KeySelector<Event, Integer>() {
@Override
public Integer getKey(Event value) throws Exception {
return value.getId();
}
});
Pattern<Event, ?> pattern = Pattern.<Event>begin("start").where(new SimpleCondition<Event>() {
@Override
public boolean filter(Event value) throws Exception {
System.out.println("testSimpleKeyedPatternCEP start -> " + value + ", " + value.getName().equals(
"start"));
return value.getName().equals("start");
}
})
.followedByAny("middle").subtype(SubEvent.class).where(
new SimpleCondition<SubEvent>() {
@Override
public boolean filter(SubEvent value) throws Exception {
System.out.println("testSimpleKeyedPatternCEP middle -> " + value + ", " + value.getName().equals("middle"));
return value.getName().equals("middle");
}
}
)
.followedByAny("end").where(new SimpleCondition<Event>() {
@Override
public boolean filter(Event value) throws Exception {
System.out.println("testSimpleKeyedPatternCEP end -> " + value + ", " + value.getName().equals(
"end"));
return value.getName().equals("end");
}
});
// 处理同一个 input 中的不同 event
DataStream<String> result = CEP.pattern(input, pattern).select(p -> {
StringBuilder builder = new StringBuilder();
builder.append(p.get("start").get(0).getId()).append