前面我们谈论了Flink stream中的transformation。你可以将transformation
看成编写Flink程序并构建流式处理程序的必要组成部分(静态表现形式);而本篇我们将探讨transformation
在Flink运行时对应的动态表现形式——operator。他们之间的映射关系见下图:
具体的探讨可以查看前文:Flink中的一些核心概念
StreamOperator
所有operator
的最终基类,operator
的分类方式,按照输入流个数不同分为:
- 无输入:StreamSource
- 单个流输入:OneInputStreamOperator
- 两个流输入:TwoInputStreamOperator
跟生命周期有关的核心抽象方法:
- setup : 实例化
operator
- open :该方法会在任何元素被处理之前执行,它的实现通常包含了
operator
的初始化逻辑 - close :该方法在所有的元素都进入到
operator
被处理之后调用 - dispose :该方法在
operator
生命周期的最后阶段执行,主要用于回收资源
StreamOperator
及其实现类中还包含了一些状态恢复与保存相关的逻辑,但这些不是本文的主题,所有暂时不做探讨。
先来看一下整个package的类关系图:
我们整个剖析方式大致也按照以上operator
的分类方式以及类的层次结构来。
StreamSource
作为一个流处理DAG的起点,source operator
相比其他operator
无疑是特别的(从类的继承关系图也可以看出来)。
它需要接受SourceFunction
的实例。并且我们可以看到,它的chaining strategy
是HEAD
(它表示operator
不能有前置operator
,但可以作为其他operator
的前置operator
,下文会谈到)。
this.chainingStrategy = ChainingStrategy.HEAD;
StreamSource
的实现略显复杂,因为它涉及到我们前面文章谈SourceFunction
时谈到的SourceFunction.SourceContext
的实现。在这里提供了三个实现,分别对应我们之前谈到的Flink对事件时间的三个分类:
- NonTimestampContext:针对
ProcessingTime
,该SourceContext
将时间戳设置为-1,并且不发射watermark
- AutomaticWatermarkContext:针对
IngestionTime
,提供自动的watermark
发射机制的SourceContext
- ManualWatermarkContext:针对
EventTime
的人工发射watermark
的SourceContext
它们之间的对应关系也体现在其run
方法的实现中:
switch (timeCharacteristic) {
case EventTime:
ctx = new ManualWatermarkContext<>(this, lockingObject, collector);
break;
case IngestionTime:
ctx = new AutomaticWatermarkContext<>(this, lockingObject, collector,
getRuntimeContext().getExecutionConfig().get