我打算以 flink 官方的 例子 <<Monitoring the Wikipedia Edit Stream>> 作为示例,进行 flink 流计算任务 的源码解析说明.
其中任务的源码如下,其中中文注释 来自
http://flink-china.org/
后续我会对这个拓扑任务代码进行逐行的深入分析,以达到深入了解flink代码运行机制的目的.
public class WikipediaAnalysis {
public static void main(String[] args) throws Exception {
//首先,构建一个StreamExecutionEnvironment
//用来设置运行参数
//当从外部系统读取数据的时候,也被用来创建源(sources)
StreamExecutionEnvironment see = StreamExecutionEnvironment.getExecutionEnvironment();
//读取 Wikipedia IRC 日志的源(sources)
DataStream<WikipediaEditEvent> edits = see.addSource(new WikipediaEditsSource());
//在本案例中,我们关心的是每个用户在一个特定时间窗口内(比如说5秒钟)增加或者删除内容的字节数。
//为了实现这个目标,我们需要指定用户名作为数据流的 key 字段,也就是说在这个数据流上的操作应该考虑到用户名。
//在我们的案例中需要对时间窗口中每个唯一用户的编辑字节数求和。为了使数据流包含 key,我们需要提供一个KeySelector.ng
KeyedStream<WikipediaEditEvent,String> keyedEdits = edits.keyBy(new KeySelector<WikipediaEditEvent, String>() {
@Override
public String getKey(WikipediaEditEvent event) {
return event.getUser();
}
});
//它创建了一个WikipediaEditEvent流,以用户名作为String类型的 key。
//现在我们可以在这个流上指定窗口并且基于这些窗口内的数据计算出结果。
//一个窗口指定了要执行计算的数据流的一个分片。当需要在一个无边界的数据流上执行聚合计算时,窗口是必不可少的。
//在我们的案例中,我们想要做的就是每5秒钟一个窗口对编辑字节数做聚合计算
DataStream<Tuple2<String, Long>> result = keyedEdits
//指定了我们需要一个大小为5秒钟的滚动窗口(非重叠窗口)
.timeWindow(Time.seconds(5))
//调用的第二个方法指定了对每个窗口分片中每个唯一的key做 Fold transformation 转换。
.fold(
new Tuple2<>("", 0L), //初始值
new FoldFunction<WikipediaEditEvent, Tuple2<String, Long>>() {
@Override
public Tuple2<String, Long> fold(Tuple2<String, Long> acc, WikipediaEditEvent event) {
acc.f0 = event.getUser();
acc.f1 += event.getByteDiff();
return acc;
}
});
//将结果流在终端输出
result.print();
//将结果输出到Kafka
//result.addSink(new FlinkKafkaProducer010<>("localhost:9092", "wiki-result", new SimpleStringSchema()));
//开始执行计算
//像前面的创建数据源,转换和 Sinks 操作仅仅是构建了一个内部操作图。
//只有当execute()被调用的时候,这个操作图才会被扔在集群或者在你的本地机器运行。
see.execute();
}
}