前置要求
- Java技术体系
- Junit单元测试
- Idea软件使用
- Flink自建版本custom-test
- Flink编程模型
Flink编程模型体系结构
接着上一篇文章的Flink编程模型,这一篇文章我们更多的是在说Flink的编程模型体系结构,或者说是API体系结构,Flink对外的技术架构并给源码进行阐述
以上就是Flink的总体技术架构,目前我们主要专注在DataStream API与部分Runtime运行时的内核源码
具体的API层次体系结构展示如下
图片来自官网: https://nightlies.apache.org/flink/flink-docs-master/docs/concepts/overview
下面我们根据上图的DataStream与ProcessFunction进行更进一步的展开说明
根据源码我们可以总结出上述体系结构的源码实现关系类图
我们从上到下展开说明一下
Fink DataStream
DataStream(包括DataStreamSource和KeyedStream)或DataStreamSink都是提供给用户对外使用的编程接口,其内部实现都是Transformation
DataStream提供了丰富的算子操作函数,例如Map/FlatMap等,而KeyedStream提供了根据Key分组后进行聚合算子操作的函数
DataStreamSource是特殊的DataStream,其内部持有SourceFunction的实现类,可以对接读取外部系统
DataStream可以理解为接收内部流数据输入,向内部输出流数据
DataStreamSource可以理解为接收内部流数据输入,但需要向外输出流数据,所以与DataStream有所不同,不能继承DataStream
从源码类关系图上可见一斑
从类关系图中我们可以看到DataStream持有Transformation和创建这个DataStream的执行环境StreamExecutionEnvironment
所以结合之前的知识,我们可以知道从执行环境StreamExecutionEnvironment创建DataStreamSource后,这个执行环境StreamExecutionEnvironment就在DataStream之间传递,用于串联DataStream之间的转换,同时Flink框架内部都是用DataStream内部持有的Transformation实现它们之间的转换的
DataStreamSink中也持有Transformation,但不持有执行环境StreamExecutionEnvironment,它是最后的一个DataStream
Flink Transformation
我们先看一下Transformation的类实现关系图
可以看出
SourceTransformation/LegacySourceTransformation: 用于从外部系统接收流数据
SinkTransformation/LegacySinkTransformation: 用于向外部系统输出流数据
OneInputTransformation: 用于单个Transformation作为输入的转换
TwoInputTransformation: 用于两个Transformation作为输入的转换
UnionTransformation: 用于多个Transformation作为输入的转换
从Transformation的类实现关系详细图中可以看出,除了SourceTransformation,每个Transformation都持有上游Transformation作为输入,同时持有构造StreamOperator的StreamOperatorFactory的工厂类
除外之外,我们还看到,Transformation内部还持有ChainingStrategy这个策略类,这个策略类主要用于实现算子之间的链子化,后续细说
Flink StreamOperator
StreamOperator是由Transformation内部持有的StreamOperatorFactory工厂类创建的
从StreamOperator的实现类或继承接口上看,StreamOperator与我们的算子操作例如Source、Sink、Map、FlatMap或Filter等是一一对应的,源码内部他们也实实在在的持有或使用相应的SourceFunction、SinkFunction、MapFunction、FlatMapFunction或FilterFunction等
从StreamOperator的类实现关系详细图中可见一斑
Flink Function
由StreamOperator内部持有的Function看,这些Function就是体系结构图里说的一系列ProcessFunction
从Function的类实现关系详细图中可以看出,每类算子操作都继承自Function,其中XxxFunction与RichXxxFunction之间的区别在于,RichXxxFunction都继承自AbstractRichFunction,其内部持有RuntimeContext运行时上下文环境
这个RuntimeContext运行时上下文环境作用可大,因为从纯算子操作函数角度来看,这些算子操作函数都应该是无状态的,但有了RuntimeContext之后我们就可以实现状态编程,后续细说
从源码Debug上探究上述体系结构的运行时实现
还是以之前testFlinkHelloWorld2的例子,这次我们命名为testFlinkTransformation
@Test
public void testFlinkTransformation() throws Exception {
DataStreamSource<String> lines = streamExecutionEnvironment.socketTextStream("localhost", 8080);
SingleOutputStreamOperator<Long> map = lines.map(((line -> Long.parseLong(line))));
map.print();
streamExecutionEnvironment.execute();
}
我们在 streamExecutionEnvironment.execute() 这一行加上调试看看效果,运行后调试定位到StreamExecutionEnvironment.execute()方法
可以看到当前StreamExecutionEnvironment的运行时实现类是LocalStreamEnvironment,StreamExecutionEnvironment内部的transformations列表存在两个实例,这个transformations列表的构建是通过DataStream之间转换成Transformation再添加到他们内部持有的StreamExecutionEnvironment里的
展开这个transformations列表细看
可以看到,transformations列表第一个位置的Transformation,其实现类是OneInputTransformation,其内部持有的input的Transformation实现类是LegacySourceTransformation,持有的StreamOperator实现类是StreamMap,这就是我们源码中的Map算子操作
同时看到transformations列表第二个位置的Transformation实现类是LegacySinkTransformation,它的input的Transformation实例就是上一个的OneInputTransformation实例,其持有的StreamOperator实现类是StreamSink
同时可以查看LegacySourceTransformation的StreamOperator实现类是StreamSource
由此我们就可以构造由transformations列表的Transformation实例所串联起来的DAG图
原文出处:
CodeRap的Gitee博客
CodeRap的Github博客
欢迎关注我的公众号:coderap_blog