Flink

Flink 作业生成①:生成 StreamGraph

2021-05-14  本文已影响0人  牛肉圆粉不加葱

一、作业生成及提交整体流程

上图为一个 Flink 作业的提交流程,主要可以分为以下几个步骤:

  1. Client 将作业 code 生成 StreamGraph(在 Batch 模式下,生成的是一个 OptimizedPlan,这里暂不展开):StreamGraph 描述了算子和算子之间逻辑上的拓扑关系
  2. Client 将 StreamGraph 转换为 JobGraph:Operator chain,
    • 将并不涉及到 shuffle 的算子进行合并
    • 对于同一个 operator chain 里面的多个算子,会在同一个 task 中执行
    • 对于不在同一个 operator chain 里的算子,会在不同的 task 中执行
  3. Client 中的 ClusterClient 将 JobGraph 提交给 Dispatcher,Dispatcher 根据 JobGraph 创建相应的 JobManager(代码上是 JobMaster)并运行起来
  4. JobManager 将 JobGraph 转换为 ExecutionGraph
  5. JobManager 将 ExecutionGraph 转换为物理执行计划(可执行)

接下来我们以如下例子来剖析各个步骤具体的执行流程:

public static void main(String[] args) throws Exception {

        // 创建 execution environment
        StreamExecutionEnvironment env = StreamExecutionEnvironment.getExecutionEnvironment();

        // 设置 data source
        DataStream<TaxiRide> rides = env.addSource(new TaxiRideGenerator());

        // 将每个 ride 转为 Tuple2(driverId, 1)
        DataStream<Tuple2<Long, Long>> tuples = rides.map(new MapFunction<TaxiRide, Tuple2<Long, Long>>() {
                    @Override
                    public Tuple2<Long, Long> map(TaxiRide ride) {
                        return Tuple2.of(ride.driverId, 1L);
                    }
        });

    // 对 stream 根据 driverId 进行重新分区
        KeyedStream<Tuple2<Long, Long>, Long> keyedByDriverId = tuples.keyBy(t -> t.f0);

        // 计算每个司机的 ride 数
        DataStream<Tuple2<Long, Long>> rideCounts = keyedByDriverId.sum(1);

        // 将结果进行打印
        rideCounts.print();

        // 开始运行
        env.execute("Ride Count");
}

二、执行 Transformations

该过程发生在 Client 端

上述代码可以分为三个部分,即:

我们分别就这三部分进行说明

2.1、输入的数据源是谁

add Source 相关的调用如下:

DataStream<TaxiRide> rides = env.addSource(new TaxiRideGenerator());

如上,通过 DataStreamSource<OUT> StreamExecutionEnvironment#addSource(SourceFunction<OUT> function) 设置 SourceFunction 并返回一个 DataStreamSource。关于 SourceFunction、SourceContext 等请查看

SourceFunction & SourceContext & StreamSource

设置输入源env.addSource(new TaxiRideGenerator()) 的流程如下:

总结一下,addSource 的主要流程如下:

2.2、对数据进行了哪些操作

以 map 操作(如下)为例,来说明 transformation 具体流程。在这里,map 将 TaxiRide 转换为 (ride.driverId, 1L) 的二元组

DataStream<Tuple2<Long, Long>> tuples = rides.map(new MapFunction<TaxiRide, Tuple2<Long, Long>>() {
         @Override
         public Tuple2<Long, Long> map(TaxiRide ride) {
            return Tuple2.of(ride.driverId, 1L);
         }
});

主要流程如下:

map 之后的 keyBysummap 有类似的过程:

  1. 获取该 transformation 的 return type info(即各个字段名和类型)
  2. 分为两种情况:
    • 若该 transformation 会对 elements 进行转换,则会
      • 使用相应的 Function 构造相应的 AbstractUdfStreamOperator;
      • 使用 return type info 和相应的 AbstractUdfStreamOperator构造 resultTransformation
      • 将 resultTransformation 添加到 env 的 List<Transformation<?>> transformations
    • 否则,创建相应的 resultTransformation(非 AbstractUdfStreamOperator 子类)
  3. 使用 resultTransformation 构造 returenDataStream: DataStream

2.3、最终计算的结果输出到哪里

最后的 rideCounts.print() 会触发 DataStream.addSink(...),其流程也如上面的几步,只是最终返回的类型是 DataStreamSink,并没有直接继承 DataStream,包含一个 transformation 。我们以下图来看 DataStream 从创建、转换、输出的过程(每个 Transformation 都有 id,从 1 开始,下面 5 个 Transformations 的 id 分别是 1、2、3、4、5):

三、生成 StreamGraph

env.execute("Ride Count") 会触发真正的执行,其内部主要分为两步:

  1. 生成 StreamGraph:通过创建 StreamGraphGenerator 并调用 generate() 方法生成 StreamGraph
  2. execute StreamGraph 返回 JobExecutionResult

我们先来看看 StreamGraph 和 StreamGraphGenerator 的一些概况,再来详细看看 StreamGraphGenerator 是如何生成 StreamGraph 的

3.1、StreamGraphGenerator 生成 StreamGraph

StreamGraphGenerator#generate() 生成 StreamGraph

如上流程图,关键的地方是看 translator 对 transformation 是如何 translateForStreaming 的,我们来看看 OneInputTransformationTranslator#translateForStreaming,这也是 map、filter 操作对应的 Translator,如下:

最终,上例中的代码生成的 StreamGraph 可以用下面这个图来表示:

在上图中:

对于 StreamGraph 及其生成,以下是一些 QA

Q:为什么上图中没有 id 为 3 的节点 ?

A:有些 transform 操作并不会生成 StreamNode。virtualSideoutputNodes、virtualPartitionNodes 这几类 transform 都会被处理成虚拟节点,当下游生成 StreamNode 后,发现上游为虚拟节点会找到虚拟节点的上游,并创建 StreamEdge 与虚拟节点上游的 transform 进行连接,并把虚拟节点信息写到 StreamEdge 中

Q:StreamGraph 还包含哪些需要注意的东西(除了上述的拓扑关系)?

A:主要有:

上一篇下一篇

猜你喜欢

热点阅读