<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/"><channel><title>源码分析 on Ralph's Blog</title><link>https://pothos.dpdns.org/tags/%E6%BA%90%E7%A0%81%E5%88%86%E6%9E%90/</link><description>Recent content in 源码分析 on Ralph's Blog</description><generator>Hugo -- 0.147.7</generator><language>zh-cn</language><lastBuildDate>Thu, 25 Dec 2025 00:00:00 +0000</lastBuildDate><atom:link href="https://pothos.dpdns.org/tags/%E6%BA%90%E7%A0%81%E5%88%86%E6%9E%90/index.xml" rel="self" type="application/rss+xml"/><item><title>12.1 Spark 源码解析</title><link>https://pothos.dpdns.org/posts/12.1-spark-%E6%BA%90%E7%A0%81%E8%A7%A3%E6%9E%90/</link><pubDate>Wed, 24 Dec 2025 00:00:00 +0000</pubDate><guid>https://pothos.dpdns.org/posts/12.1-spark-%E6%BA%90%E7%A0%81%E8%A7%A3%E6%9E%90/</guid><description>&lt;h1 id="121-spark源码解析">12.1 Spark源码解析&lt;/h1>
&lt;h2 id="目录">目录&lt;/h2>
&lt;details>
&lt;summary>点击展开目录&lt;/summary>
&lt;h3 id="一spark核心架构与初始化">一、Spark核心架构与初始化&lt;/h3>
&lt;ul>
&lt;li>&lt;a href="#11-sparkcontext%E5%88%9D%E5%A7%8B%E5%8C%96%E6%B5%81%E7%A8%8B">1.1 SparkContext初始化流程&lt;/a>&lt;/li>
&lt;li>&lt;a href="#12-%E8%BF%90%E8%A1%8C%E7%8E%AF%E5%A2%83%E6%9E%84%E5%BB%BA">1.2 运行环境构建&lt;/a>&lt;/li>
&lt;/ul>
&lt;h3 id="二rdd设计与实现">二、RDD设计与实现&lt;/h3>
&lt;ul>
&lt;li>&lt;a href="#21-rdd%E6%A0%B8%E5%BF%83%E6%8A%BD%E8%B1%A1">2.1 RDD核心抽象&lt;/a>&lt;/li>
&lt;li>&lt;a href="#22-rdd%E4%BA%94%E5%A4%A7%E7%89%B9%E6%80%A7">2.2 RDD五大特性&lt;/a>&lt;/li>
&lt;li>&lt;a href="#23-rdd%E6%93%8D%E4%BD%9C%E6%89%A7%E8%A1%8C">2.3 RDD操作执行&lt;/a>&lt;/li>
&lt;/ul>
&lt;h3 id="三任务调度系统">三、任务调度系统&lt;/h3>
&lt;ul>
&lt;li>&lt;a href="#31-dagscheduler%E8%B0%83%E5%BA%A6%E5%99%A8">3.1 DAGScheduler调度器&lt;/a>&lt;/li>
&lt;li>&lt;a href="#32-stage%E5%88%92%E5%88%86%E7%AE%97%E6%B3%95">3.2 Stage划分算法&lt;/a>&lt;/li>
&lt;li>&lt;a href="#33-taskscheduler%E4%BB%BB%E5%8A%A1%E8%B0%83%E5%BA%A6">3.3 TaskScheduler任务调度&lt;/a>&lt;/li>
&lt;li>&lt;a href="#34-task%E6%89%A7%E8%A1%8C%E6%9C%BA%E5%88%B6">3.4 Task执行机制&lt;/a>&lt;/li>
&lt;li>&lt;a href="#35-%E4%BB%BB%E5%8A%A1%E5%88%86%E5%8F%91%E4%B8%8E%E8%B0%83%E5%BA%A6%E6%B5%81%E7%A8%8B">3.5 任务分发与调度流程&lt;/a>&lt;/li>
&lt;li>&lt;a href="#36-%E5%AE%B9%E9%94%99%E4%B8%8E%E7%9B%91%E6%8E%A7%E6%9C%BA%E5%88%B6">3.6 容错与监控机制&lt;/a>&lt;/li>
&lt;li>&lt;a href="#37-%E5%A4%B1%E8%B4%A5%E9%87%8D%E8%AF%95%E6%9C%BA%E5%88%B6">3.7 失败重试机制&lt;/a>&lt;/li>
&lt;li>&lt;a href="#38-rdd%E8%A1%80%E7%BB%9F%E6%81%A2%E5%A4%8D">3.8 RDD血统恢复&lt;/a>&lt;/li>
&lt;/ul>
&lt;h3 id="四内存管理系统">四、内存管理系统&lt;/h3>
&lt;ul>
&lt;li>&lt;a href="#41-%E7%BB%9F%E4%B8%80%E5%86%85%E5%AD%98%E7%AE%A1%E7%90%86">4.1 统一内存管理&lt;/a>&lt;/li>
&lt;li>&lt;a href="#42-%E7%AE%97%E5%AD%90%E5%86%85%E5%AD%98%E5%AD%98%E5%82%A8">4.2 算子内存存储&lt;/a>&lt;/li>
&lt;li>&lt;a href="#43-%E5%86%85%E5%AD%98%E7%9B%91%E6%8E%A7%E4%B8%8E%E4%BC%98%E5%8C%96">4.3 内存监控与优化&lt;/a>&lt;/li>
&lt;li>&lt;a href="#44-%E5%86%85%E5%AD%98%E7%AE%A1%E7%90%86%E7%B3%BB%E7%BB%9F%E9%AB%98%E7%BA%A7%E7%89%B9%E6%80%A7">4.4 内存管理系统（高级特性）&lt;/a>&lt;/li>
&lt;li>&lt;a href="#45-%E7%BB%9F%E4%B8%80%E5%86%85%E5%AD%98%E7%AE%A1%E7%90%86%E8%AF%A6%E7%BB%86%E5%AE%9E%E7%8E%B0">4.5 统一内存管理（详细实现）&lt;/a>&lt;/li>
&lt;/ul>
&lt;h3 id="五shuffle机制实现">五、Shuffle机制实现&lt;/h3>
&lt;ul>
&lt;li>&lt;a href="#51-sort-shuffle%E6%A0%B8%E5%BF%83">5.1 Sort Shuffle核心&lt;/a>&lt;/li>
&lt;li>&lt;a href="#52-unsafeshufflewriter">5.2 UnsafeShuffleWriter&lt;/a>&lt;/li>
&lt;/ul>
&lt;h3 id="六存储系统设计">六、存储系统设计&lt;/h3>
&lt;ul>
&lt;li>&lt;a href="#61-blockmanager%E5%AD%98%E5%82%A8">6.1 BlockManager存储&lt;/a>&lt;/li>
&lt;li>&lt;a href="#62-%E7%BC%93%E5%AD%98%E6%9C%BA%E5%88%B6">6.2 缓存机制&lt;/a>&lt;/li>
&lt;/ul>
&lt;h3 id="七网络通信系统">七、网络通信系统&lt;/h3>
&lt;ul>
&lt;li>&lt;a href="#71-%E7%BD%91%E7%BB%9C%E4%BC%A0%E8%BE%93%E6%9C%8D%E5%8A%A1">7.1 网络传输服务&lt;/a>&lt;/li>
&lt;li>&lt;a href="#72-block%E4%BC%A0%E8%BE%93%E6%9C%BA%E5%88%B6">7.2 Block传输机制&lt;/a>&lt;/li>
&lt;/ul>
&lt;h3 id="八动态资源分配">八、动态资源分配&lt;/h3>
&lt;ul>
&lt;li>&lt;a href="#81-%E8%B5%84%E6%BA%90%E5%88%86%E9%85%8D%E7%AD%96%E7%95%A5">8.1 资源分配策略&lt;/a>&lt;/li>
&lt;li>&lt;a href="#82-%E5%8A%A8%E6%80%81%E4%BC%B8%E7%BC%A9%E7%AE%97%E6%B3%95">8.2 动态伸缩算法&lt;/a>&lt;/li>
&lt;/ul>
&lt;h3 id="九spark-sql执行引擎">九、Spark SQL执行引擎&lt;/h3>
&lt;ul>
&lt;li>&lt;a href="#91-catalyst%E4%BC%98%E5%8C%96%E5%99%A8%E6%A0%B8%E5%BF%83">9.1 Catalyst优化器核心&lt;/a>&lt;/li>
&lt;li>&lt;a href="#92-%E4%BB%A3%E7%A0%81%E7%94%9F%E6%88%90%E4%B8%8E%E6%89%A7%E8%A1%8C">9.2 代码生成与执行&lt;/a>&lt;/li>
&lt;li>&lt;a href="#93-%E5%88%97%E5%BC%8F%E5%AD%98%E5%82%A8%E4%B8%8E%E5%90%91%E9%87%8F%E5%8C%96">9.3 列式存储与向量化&lt;/a>&lt;/li>
&lt;li>&lt;a href="#94-%E8%87%AA%E9%80%82%E5%BA%94%E6%9F%A5%E8%AF%A2%E6%89%A7%E8%A1%8Caqe">9.4 自适应查询执行(AQE)&lt;/a>&lt;/li>
&lt;li>&lt;a href="#95-%E7%AA%97%E5%8F%A3%E5%87%BD%E6%95%B0%E5%AE%9E%E7%8E%B0%E5%8E%9F%E7%90%86%E4%BB%A5-lag-%E4%B8%BA%E4%BE%8B">9.5 窗口函数实现原理（以 Lag 为例）&lt;/a>&lt;/li>
&lt;/ul>
&lt;h3 id="十广播变量与累加器">十、广播变量与累加器&lt;/h3>
&lt;ul>
&lt;li>&lt;a href="#101-%E5%B9%BF%E6%92%AD%E5%8F%98%E9%87%8F%E5%AE%9E%E7%8E%B0%E6%9C%BA%E5%88%B6">10.1 广播变量实现机制&lt;/a>&lt;/li>
&lt;li>&lt;a href="#102-%E7%B4%AF%E5%8A%A0%E5%99%A8%E6%BA%90%E7%A0%81%E5%88%86%E6%9E%90">10.2 累加器源码分析&lt;/a>&lt;/li>
&lt;/ul>
&lt;h3 id="十一检查点与容错机制">十一、检查点与容错机制&lt;/h3>
&lt;ul>
&lt;li>&lt;a href="#111-%E6%A3%80%E6%9F%A5%E7%82%B9%E6%9C%BA%E5%88%B6%E5%AE%9E%E7%8E%B0">11.1 检查点机制实现&lt;/a>&lt;/li>
&lt;li>&lt;a href="#112-%E5%A4%B1%E8%B4%A5%E9%87%8D%E8%AF%95%E4%B8%8E%E8%A1%80%E7%BB%9F%E6%81%A2%E5%A4%8D">11.2 失败重试与血统恢复&lt;/a>&lt;/li>
&lt;/ul>
&lt;h3 id="十二集群管理器集成">十二、集群管理器集成&lt;/h3>
&lt;ul>
&lt;li>&lt;a href="#121-yarn%E9%9B%86%E6%88%90%E6%BA%90%E7%A0%81">12.1 YARN集成源码&lt;/a>&lt;/li>
&lt;li>&lt;a href="#122-kubernetes%E9%9B%86%E6%88%90">12.2 Kubernetes集成&lt;/a>&lt;/li>
&lt;/ul>
&lt;hr>
&lt;/details>
&lt;h2 id="一spark核心架构与初始化-1">一、Spark核心架构与初始化&lt;/h2>
&lt;h3 id="11-sparkcontext初始化流程">1.1 SparkContext初始化流程&lt;/h3>
&lt;h4 id="sparkcontext初始化流程图">SparkContext初始化流程图&lt;/h4>
&lt;div class="mermaid">graph TD
A[SparkContext构造] --> B[创建SparkConf配置]
B --> C[创建SparkEnv运行环境]
C --> D[创建StatusTracker状态跟踪器]
D --> E[创建TaskScheduler任务调度器]
E --> F[创建DAGScheduler DAG调度器]
F --> G[启动TaskScheduler]
G --> H[设置默认并行度]
H --> I[SparkContext初始化完成]
C --> C1[创建SerializerManager]
C --> C2[创建BlockManager]
C --> C3[创建MemoryManager]
C --> C4[创建MetricsSystem]
E --> E1[根据master创建调度器]
E1 --> E2[Standalone模式]
E1 --> E3[YARN模式]
E1 --> E4[Local模式]
style A fill:#e1f5fe
style I fill:#e8f5e8
style C fill:#fff3e0
style F fill:#f3e5f5
&lt;/div>
&lt;h3 id="12-运行环境构建">1.2 运行环境构建&lt;/h3>
&lt;h4 id="sparkcontext初始化源码分析">SparkContext初始化源码分析&lt;/h4>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-scala" data-lang="scala">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">// SparkContext.scala 核心初始化流程
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>&lt;span style="color:#66d9ef">class&lt;/span> &lt;span style="color:#a6e22e">SparkContext&lt;/span>&lt;span style="color:#f92672">(&lt;/span>config&lt;span style="color:#66d9ef">:&lt;/span> &lt;span style="color:#66d9ef">SparkConf&lt;/span>&lt;span style="color:#f92672">)&lt;/span> &lt;span style="color:#66d9ef">extends&lt;/span> &lt;span style="color:#a6e22e">Logging&lt;/span> &lt;span style="color:#f92672">{&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e">// 1. 创建SparkEnv - 核心运行环境
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span> &lt;span style="color:#66d9ef">private&lt;/span> &lt;span style="color:#66d9ef">val&lt;/span> env&lt;span style="color:#66d9ef">:&lt;/span> &lt;span style="color:#66d9ef">SparkEnv&lt;/span> &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#f92672">{&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">SparkEnv&lt;/span>&lt;span style="color:#f92672">.&lt;/span>createDriverEnv&lt;span style="color:#f92672">(&lt;/span>conf&lt;span style="color:#f92672">,&lt;/span> isLocal&lt;span style="color:#f92672">,&lt;/span> listenerBus&lt;span style="color:#f92672">,&lt;/span> numCores&lt;span style="color:#f92672">,&lt;/span> mockOutputCommitCoordinator&lt;span style="color:#f92672">)&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">}&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e">// 2. 创建状态跟踪器
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span> &lt;span style="color:#66d9ef">private&lt;/span> &lt;span style="color:#66d9ef">val&lt;/span> statusTracker &lt;span style="color:#66d9ef">=&lt;/span> &lt;span style="color:#66d9ef">new&lt;/span> &lt;span style="color:#a6e22e">SparkStatusTracker&lt;/span>&lt;span style="color:#f92672">(&lt;/span>&lt;span style="color:#66d9ef">this&lt;/span>&lt;span style="color:#f92672">,&lt;/span> sparkUI&lt;span style="color:#f92672">)&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e">// 3. 创建任务调度器
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span> &lt;span style="color:#66d9ef">private&lt;/span> &lt;span style="color:#66d9ef">val&lt;/span> &lt;span style="color:#f92672">(&lt;/span>sched&lt;span style="color:#f92672">,&lt;/span> ts&lt;span style="color:#f92672">)&lt;/span> &lt;span style="color:#66d9ef">=&lt;/span> &lt;span style="color:#a6e22e">SparkContext&lt;/span>&lt;span style="color:#f92672">.&lt;/span>createTaskScheduler&lt;span style="color:#f92672">(&lt;/span>&lt;span style="color:#66d9ef">this&lt;/span>&lt;span style="color:#f92672">,&lt;/span> master&lt;span style="color:#f92672">,&lt;/span> deployMode&lt;span style="color:#f92672">)&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">private&lt;/span> &lt;span style="color:#66d9ef">val&lt;/span> taskScheduler &lt;span style="color:#66d9ef">=&lt;/span> ts
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e">// 4. 创建DAG调度器
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span> &lt;span style="color:#66d9ef">private&lt;/span> &lt;span style="color:#66d9ef">val&lt;/span> dagScheduler &lt;span style="color:#66d9ef">=&lt;/span> &lt;span style="color:#66d9ef">new&lt;/span> &lt;span style="color:#a6e22e">DAGScheduler&lt;/span>&lt;span style="color:#f92672">(&lt;/span>&lt;span style="color:#66d9ef">this&lt;/span>&lt;span style="color:#f92672">)&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e">// 5. 启动任务调度器
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span> taskScheduler&lt;span style="color:#f92672">.&lt;/span>start&lt;span style="color:#f92672">()&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e">// 6. 设置默认并行度
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span> &lt;span style="color:#66d9ef">private&lt;/span> &lt;span style="color:#66d9ef">val&lt;/span> defaultParallelism&lt;span style="color:#66d9ef">:&lt;/span> &lt;span style="color:#66d9ef">Int&lt;/span> &lt;span style="color:#f92672">=&lt;/span> taskScheduler&lt;span style="color:#f92672">.&lt;/span>defaultParallelism
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e">// 核心方法：创建RDD
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span> &lt;span style="color:#66d9ef">def&lt;/span> parallelize&lt;span style="color:#f92672">[&lt;/span>&lt;span style="color:#66d9ef">T:&lt;/span> &lt;span style="color:#66d9ef">ClassTag&lt;/span>&lt;span style="color:#f92672">](&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> seq&lt;span style="color:#66d9ef">:&lt;/span> &lt;span style="color:#66d9ef">Seq&lt;/span>&lt;span style="color:#f92672">[&lt;/span>&lt;span style="color:#66d9ef">T&lt;/span>&lt;span style="color:#f92672">],&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> numSlices&lt;span style="color:#66d9ef">:&lt;/span> &lt;span style="color:#66d9ef">Int&lt;/span> &lt;span style="color:#f92672">=&lt;/span> defaultParallelism&lt;span style="color:#f92672">)&lt;/span>&lt;span style="color:#66d9ef">:&lt;/span> &lt;span style="color:#66d9ef">RDD&lt;/span>&lt;span style="color:#f92672">[&lt;/span>&lt;span style="color:#66d9ef">T&lt;/span>&lt;span style="color:#f92672">]&lt;/span> &lt;span style="color:#66d9ef">=&lt;/span> withScope &lt;span style="color:#f92672">{&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">new&lt;/span> &lt;span style="color:#a6e22e">ParallelCollectionRDD&lt;/span>&lt;span style="color:#f92672">[&lt;/span>&lt;span style="color:#66d9ef">T&lt;/span>&lt;span style="color:#f92672">](&lt;/span>&lt;span style="color:#66d9ef">this&lt;/span>&lt;span style="color:#f92672">,&lt;/span> seq&lt;span style="color:#f92672">,&lt;/span> numSlices&lt;span style="color:#f92672">,&lt;/span> &lt;span style="color:#a6e22e">Map&lt;/span>&lt;span style="color:#f92672">[&lt;/span>&lt;span style="color:#66d9ef">Int&lt;/span>, &lt;span style="color:#66d9ef">Seq&lt;/span>&lt;span style="color:#f92672">[&lt;/span>&lt;span style="color:#66d9ef">String&lt;/span>&lt;span style="color:#f92672">]]())&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">}&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e">// 核心方法：提交作业
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span> &lt;span style="color:#66d9ef">def&lt;/span> runJob&lt;span style="color:#f92672">[&lt;/span>&lt;span style="color:#66d9ef">T&lt;/span>, &lt;span style="color:#66d9ef">U:&lt;/span> &lt;span style="color:#66d9ef">ClassTag&lt;/span>&lt;span style="color:#f92672">](&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> rdd&lt;span style="color:#66d9ef">:&lt;/span> &lt;span style="color:#66d9ef">RDD&lt;/span>&lt;span style="color:#f92672">[&lt;/span>&lt;span style="color:#66d9ef">T&lt;/span>&lt;span style="color:#f92672">],&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> func&lt;span style="color:#66d9ef">:&lt;/span> &lt;span style="color:#f92672">(&lt;/span>&lt;span style="color:#66d9ef">TaskContext&lt;/span>&lt;span style="color:#f92672">,&lt;/span> &lt;span style="color:#66d9ef">Iterator&lt;/span>&lt;span style="color:#f92672">[&lt;/span>&lt;span style="color:#66d9ef">T&lt;/span>&lt;span style="color:#f92672">])&lt;/span> &lt;span style="color:#66d9ef">=&amp;gt;&lt;/span> U&lt;span style="color:#f92672">,&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> partitions&lt;span style="color:#66d9ef">:&lt;/span> &lt;span style="color:#66d9ef">Seq&lt;/span>&lt;span style="color:#f92672">[&lt;/span>&lt;span style="color:#66d9ef">Int&lt;/span>&lt;span style="color:#f92672">],&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> resultHandler&lt;span style="color:#66d9ef">:&lt;/span> &lt;span style="color:#f92672">(&lt;/span>&lt;span style="color:#66d9ef">Int&lt;/span>&lt;span style="color:#f92672">,&lt;/span> &lt;span style="color:#66d9ef">U&lt;/span>&lt;span style="color:#f92672">)&lt;/span> &lt;span style="color:#66d9ef">=&amp;gt;&lt;/span> &lt;span style="color:#a6e22e">Unit&lt;/span>&lt;span style="color:#f92672">)&lt;/span>&lt;span style="color:#66d9ef">:&lt;/span> &lt;span style="color:#66d9ef">Unit&lt;/span> &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#f92672">{&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> dagScheduler&lt;span style="color:#f92672">.&lt;/span>runJob&lt;span style="color:#f92672">(&lt;/span>rdd&lt;span style="color:#f92672">,&lt;/span> func&lt;span style="color:#f92672">,&lt;/span> partitions&lt;span style="color:#f92672">,&lt;/span> callSite&lt;span style="color:#f92672">,&lt;/span> resultHandler&lt;span style="color:#f92672">,&lt;/span> localProperties&lt;span style="color:#f92672">.&lt;/span>get&lt;span style="color:#f92672">)&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">}&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f92672">}&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;hr>
&lt;h2 id="二rdd设计与实现-1">二、RDD设计与实现&lt;/h2>
&lt;h3 id="21-rdd核心抽象">2.1 RDD核心抽象&lt;/h3>
&lt;h4 id="rdd五大特性实现流程">RDD五大特性实现流程&lt;/h4>
&lt;div class="mermaid">graph LR
A[RDD实例化] --> B[getPartitions&lt;br/>获取分区列表]
B --> C[compute&lt;br/>定义计算函数]
C --> D[getDependencies&lt;br/>设置依赖关系]
D --> E[partitioner&lt;br/>设置分区器]
E --> F[getPreferredLocations&lt;br/>位置偏好]
F --> G[RDD创建完成]
style A fill:#e1f5fe
style G fill:#e8f5e8
&lt;/div>
&lt;h3 id="22-rdd五大特性">2.2 RDD五大特性&lt;/h3>
&lt;h4 id="rdd源码核心实现">RDD源码核心实现&lt;/h4>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-scala" data-lang="scala">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">// RDD.scala 核心抽象
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>&lt;span style="color:#66d9ef">abstract&lt;/span> &lt;span style="color:#66d9ef">class&lt;/span> &lt;span style="color:#a6e22e">RDD&lt;/span>&lt;span style="color:#f92672">[&lt;/span>&lt;span style="color:#66d9ef">T:&lt;/span> &lt;span style="color:#66d9ef">ClassTag&lt;/span>&lt;span style="color:#f92672">](&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">@transient&lt;/span> &lt;span style="color:#66d9ef">private&lt;/span> &lt;span style="color:#66d9ef">var&lt;/span> &lt;span style="color:#a6e22e">_sc&lt;/span>&lt;span style="color:#66d9ef">:&lt;/span> &lt;span style="color:#66d9ef">SparkContext&lt;/span>&lt;span style="color:#f92672">,&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">@transient&lt;/span> &lt;span style="color:#66d9ef">private&lt;/span> &lt;span style="color:#66d9ef">var&lt;/span> deps&lt;span style="color:#66d9ef">:&lt;/span> &lt;span style="color:#66d9ef">Seq&lt;/span>&lt;span style="color:#f92672">[&lt;/span>&lt;span style="color:#66d9ef">Dependency&lt;/span>&lt;span style="color:#f92672">[&lt;/span>&lt;span style="color:#66d9ef">_&lt;/span>&lt;span style="color:#f92672">]]&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">)&lt;/span> &lt;span style="color:#66d9ef">extends&lt;/span> &lt;span style="color:#a6e22e">Serializable&lt;/span> &lt;span style="color:#66d9ef">with&lt;/span> &lt;span style="color:#a6e22e">Logging&lt;/span> &lt;span style="color:#f92672">{&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e">// 五大特性的具体实现
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e">// 1. 分区列表
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span> &lt;span style="color:#66d9ef">protected&lt;/span> &lt;span style="color:#66d9ef">def&lt;/span> getPartitions&lt;span style="color:#66d9ef">:&lt;/span> &lt;span style="color:#66d9ef">Array&lt;/span>&lt;span style="color:#f92672">[&lt;/span>&lt;span style="color:#66d9ef">Partition&lt;/span>&lt;span style="color:#f92672">]&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e">// 2. 计算函数
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span> &lt;span style="color:#66d9ef">def&lt;/span> compute&lt;span style="color:#f92672">(&lt;/span>split&lt;span style="color:#66d9ef">:&lt;/span> &lt;span style="color:#66d9ef">Partition&lt;/span>&lt;span style="color:#f92672">,&lt;/span> context&lt;span style="color:#66d9ef">:&lt;/span> &lt;span style="color:#66d9ef">TaskContext&lt;/span>&lt;span style="color:#f92672">)&lt;/span>&lt;span style="color:#66d9ef">:&lt;/span> &lt;span style="color:#66d9ef">Iterator&lt;/span>&lt;span style="color:#f92672">[&lt;/span>&lt;span style="color:#66d9ef">T&lt;/span>&lt;span style="color:#f92672">]&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e">// 3. 依赖关系
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span> &lt;span style="color:#66d9ef">protected&lt;/span> &lt;span style="color:#66d9ef">def&lt;/span> getDependencies&lt;span style="color:#66d9ef">:&lt;/span> &lt;span style="color:#66d9ef">Seq&lt;/span>&lt;span style="color:#f92672">[&lt;/span>&lt;span style="color:#66d9ef">Dependency&lt;/span>&lt;span style="color:#f92672">[&lt;/span>&lt;span style="color:#66d9ef">_&lt;/span>&lt;span style="color:#f92672">]]&lt;/span> &lt;span style="color:#66d9ef">=&lt;/span> deps
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e">// 4. 分区器（可选）
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span> &lt;span style="color:#a6e22e">@transient&lt;/span> &lt;span style="color:#66d9ef">val&lt;/span> partitioner&lt;span style="color:#66d9ef">:&lt;/span> &lt;span style="color:#66d9ef">Option&lt;/span>&lt;span style="color:#f92672">[&lt;/span>&lt;span style="color:#66d9ef">Partitioner&lt;/span>&lt;span style="color:#f92672">]&lt;/span> &lt;span style="color:#66d9ef">=&lt;/span> &lt;span style="color:#a6e22e">None&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e">// 5. 位置偏好（可选）
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span> &lt;span style="color:#66d9ef">protected&lt;/span> &lt;span style="color:#66d9ef">def&lt;/span> getPreferredLocations&lt;span style="color:#f92672">(&lt;/span>split&lt;span style="color:#66d9ef">:&lt;/span> &lt;span style="color:#66d9ef">Partition&lt;/span>&lt;span style="color:#f92672">)&lt;/span>&lt;span style="color:#66d9ef">:&lt;/span> &lt;span style="color:#66d9ef">Seq&lt;/span>&lt;span style="color:#f92672">[&lt;/span>&lt;span style="color:#66d9ef">String&lt;/span>&lt;span style="color:#f92672">]&lt;/span> &lt;span style="color:#66d9ef">=&lt;/span> &lt;span style="color:#a6e22e">Nil&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e">// Transformation操作实现
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span> &lt;span style="color:#66d9ef">def&lt;/span> map&lt;span style="color:#f92672">[&lt;/span>&lt;span style="color:#66d9ef">U:&lt;/span> &lt;span style="color:#66d9ef">ClassTag&lt;/span>&lt;span style="color:#f92672">](&lt;/span>f&lt;span style="color:#66d9ef">:&lt;/span> &lt;span style="color:#66d9ef">T&lt;/span> &lt;span style="color:#f92672">=&amp;gt;&lt;/span> U&lt;span style="color:#f92672">)&lt;/span>&lt;span style="color:#66d9ef">:&lt;/span> &lt;span style="color:#66d9ef">RDD&lt;/span>&lt;span style="color:#f92672">[&lt;/span>&lt;span style="color:#66d9ef">U&lt;/span>&lt;span style="color:#f92672">]&lt;/span> &lt;span style="color:#66d9ef">=&lt;/span> withScope &lt;span style="color:#f92672">{&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">val&lt;/span> cleanF &lt;span style="color:#66d9ef">=&lt;/span> sc&lt;span style="color:#f92672">.&lt;/span>clean&lt;span style="color:#f92672">(&lt;/span>f&lt;span style="color:#f92672">)&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">new&lt;/span> &lt;span style="color:#a6e22e">MapPartitionsRDD&lt;/span>&lt;span style="color:#f92672">[&lt;/span>&lt;span style="color:#66d9ef">U&lt;/span>, &lt;span style="color:#66d9ef">T&lt;/span>&lt;span style="color:#f92672">](&lt;/span>&lt;span style="color:#66d9ef">this&lt;/span>&lt;span style="color:#f92672">,&lt;/span> &lt;span style="color:#f92672">(&lt;/span>context&lt;span style="color:#f92672">,&lt;/span> pid&lt;span style="color:#f92672">,&lt;/span> iter&lt;span style="color:#f92672">)&lt;/span> &lt;span style="color:#66d9ef">=&amp;gt;&lt;/span> iter&lt;span style="color:#f92672">.&lt;/span>map&lt;span style="color:#f92672">(&lt;/span>cleanF&lt;span style="color:#f92672">))&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">}&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">def&lt;/span> filter&lt;span style="color:#f92672">(&lt;/span>f&lt;span style="color:#66d9ef">:&lt;/span> &lt;span style="color:#66d9ef">T&lt;/span> &lt;span style="color:#f92672">=&amp;gt;&lt;/span> &lt;span style="color:#a6e22e">Boolean&lt;/span>&lt;span style="color:#f92672">)&lt;/span>&lt;span style="color:#66d9ef">:&lt;/span> &lt;span style="color:#66d9ef">RDD&lt;/span>&lt;span style="color:#f92672">[&lt;/span>&lt;span style="color:#66d9ef">T&lt;/span>&lt;span style="color:#f92672">]&lt;/span> &lt;span style="color:#66d9ef">=&lt;/span> withScope &lt;span style="color:#f92672">{&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">val&lt;/span> cleanF &lt;span style="color:#66d9ef">=&lt;/span> sc&lt;span style="color:#f92672">.&lt;/span>clean&lt;span style="color:#f92672">(&lt;/span>f&lt;span style="color:#f92672">)&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">new&lt;/span> &lt;span style="color:#a6e22e">MapPartitionsRDD&lt;/span>&lt;span style="color:#f92672">[&lt;/span>&lt;span style="color:#66d9ef">T&lt;/span>, &lt;span style="color:#66d9ef">T&lt;/span>&lt;span style="color:#f92672">](&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">this&lt;/span>&lt;span style="color:#f92672">,&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">(&lt;/span>context&lt;span style="color:#f92672">,&lt;/span> pid&lt;span style="color:#f92672">,&lt;/span> iter&lt;span style="color:#f92672">)&lt;/span> &lt;span style="color:#66d9ef">=&amp;gt;&lt;/span> iter&lt;span style="color:#f92672">.&lt;/span>filter&lt;span style="color:#f92672">(&lt;/span>cleanF&lt;span style="color:#f92672">),&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> preservesPartitioning &lt;span style="color:#66d9ef">=&lt;/span> &lt;span style="color:#66d9ef">true&lt;/span>&lt;span style="color:#f92672">)&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">}&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">def&lt;/span> reduceByKey&lt;span style="color:#f92672">(&lt;/span>func&lt;span style="color:#66d9ef">:&lt;/span> &lt;span style="color:#f92672">(&lt;/span>&lt;span style="color:#66d9ef">T&lt;/span>&lt;span style="color:#f92672">,&lt;/span> &lt;span style="color:#66d9ef">T&lt;/span>&lt;span style="color:#f92672">)&lt;/span> &lt;span style="color:#66d9ef">=&amp;gt;&lt;/span> T&lt;span style="color:#f92672">)&lt;/span>&lt;span style="color:#66d9ef">:&lt;/span> &lt;span style="color:#66d9ef">RDD&lt;/span>&lt;span style="color:#f92672">[&lt;/span>&lt;span style="color:#66d9ef">T&lt;/span>&lt;span style="color:#f92672">]&lt;/span> &lt;span style="color:#66d9ef">=&lt;/span> self&lt;span style="color:#f92672">.&lt;/span>withScope &lt;span style="color:#f92672">{&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> reduceByKey&lt;span style="color:#f92672">(&lt;/span>defaultPartitioner&lt;span style="color:#f92672">(&lt;/span>self&lt;span style="color:#f92672">),&lt;/span> func&lt;span style="color:#f92672">)&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">}&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e">// Action操作实现
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span> &lt;span style="color:#66d9ef">def&lt;/span> collect&lt;span style="color:#f92672">()&lt;/span>&lt;span style="color:#66d9ef">:&lt;/span> &lt;span style="color:#66d9ef">Array&lt;/span>&lt;span style="color:#f92672">[&lt;/span>&lt;span style="color:#66d9ef">T&lt;/span>&lt;span style="color:#f92672">]&lt;/span> &lt;span style="color:#66d9ef">=&lt;/span> withScope &lt;span style="color:#f92672">{&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">val&lt;/span> results &lt;span style="color:#66d9ef">=&lt;/span> sc&lt;span style="color:#f92672">.&lt;/span>runJob&lt;span style="color:#f92672">(&lt;/span>&lt;span style="color:#66d9ef">this&lt;/span>&lt;span style="color:#f92672">,&lt;/span> &lt;span style="color:#f92672">(&lt;/span>iter&lt;span style="color:#66d9ef">:&lt;/span> &lt;span style="color:#66d9ef">Iterator&lt;/span>&lt;span style="color:#f92672">[&lt;/span>&lt;span style="color:#66d9ef">T&lt;/span>&lt;span style="color:#f92672">])&lt;/span> &lt;span style="color:#66d9ef">=&amp;gt;&lt;/span> iter&lt;span style="color:#f92672">.&lt;/span>toArray&lt;span style="color:#f92672">)&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">Array&lt;/span>&lt;span style="color:#f92672">.&lt;/span>concat&lt;span style="color:#f92672">(&lt;/span>results&lt;span style="color:#66d9ef">:&lt;/span> &lt;span style="color:#66d9ef">_&lt;/span>&lt;span style="color:#66d9ef">*&lt;/span>&lt;span style="color:#f92672">)&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">}&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">def&lt;/span> count&lt;span style="color:#f92672">()&lt;/span>&lt;span style="color:#66d9ef">:&lt;/span> &lt;span style="color:#66d9ef">Long&lt;/span> &lt;span style="color:#f92672">=&lt;/span> sc&lt;span style="color:#f92672">.&lt;/span>runJob&lt;span style="color:#f92672">(&lt;/span>&lt;span style="color:#66d9ef">this&lt;/span>&lt;span style="color:#f92672">,&lt;/span> &lt;span style="color:#a6e22e">Utils&lt;/span>&lt;span style="color:#f92672">.&lt;/span>getIteratorSize &lt;span style="color:#66d9ef">_&lt;/span>&lt;span style="color:#f92672">).&lt;/span>sum
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">def&lt;/span> foreach&lt;span style="color:#f92672">(&lt;/span>f&lt;span style="color:#66d9ef">:&lt;/span> &lt;span style="color:#66d9ef">T&lt;/span> &lt;span style="color:#f92672">=&amp;gt;&lt;/span> &lt;span style="color:#a6e22e">Unit&lt;/span>&lt;span style="color:#f92672">)&lt;/span>&lt;span style="color:#66d9ef">:&lt;/span> &lt;span style="color:#66d9ef">Unit&lt;/span> &lt;span style="color:#f92672">=&lt;/span> withScope &lt;span style="color:#f92672">{&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">val&lt;/span> cleanF &lt;span style="color:#66d9ef">=&lt;/span> sc&lt;span style="color:#f92672">.&lt;/span>clean&lt;span style="color:#f92672">(&lt;/span>f&lt;span style="color:#f92672">)&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> sc&lt;span style="color:#f92672">.&lt;/span>runJob&lt;span style="color:#f92672">(&lt;/span>&lt;span style="color:#66d9ef">this&lt;/span>&lt;span style="color:#f92672">,&lt;/span> &lt;span style="color:#f92672">(&lt;/span>iter&lt;span style="color:#66d9ef">:&lt;/span> &lt;span style="color:#66d9ef">Iterator&lt;/span>&lt;span style="color:#f92672">[&lt;/span>&lt;span style="color:#66d9ef">T&lt;/span>&lt;span style="color:#f92672">])&lt;/span> &lt;span style="color:#66d9ef">=&amp;gt;&lt;/span> iter&lt;span style="color:#f92672">.&lt;/span>foreach&lt;span style="color:#f92672">(&lt;/span>cleanF&lt;span style="color:#f92672">))&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">}&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f92672">}&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h3 id="23-rdd操作执行">2.3 RDD操作执行&lt;/h3>
&lt;h4 id="rdd操作执行流程图">RDD操作执行流程图&lt;/h4>
&lt;div class="mermaid">graph TD
A[RDD操作调用] --> B{操作类型}
B -->|Transformation| C[创建新RDD]
B -->|Action| D[触发作业执行]
C --> C1[构建RDD血统]
C1 --> C2[设置依赖关系]
C2 --> C3[返回新RDD对象]
C3 --> E[等待Action触发]
D --> D1[调用SparkContext.runJob]
D1 --> D2[DAGScheduler.runJob]
D2 --> D3[构建DAG图]
D3 --> D4[划分Stage]
D4 --> D5[提交Task]
D5 --> D6[Executor执行]
D6 --> D7[返回结果]
style C fill:#e8f5e8
style D fill:#ffebee
style D3 fill:#fff3e0
style D6 fill:#e1f5fe
&lt;/div>
&lt;hr>
&lt;h2 id="三任务调度系统-1">三、任务调度系统&lt;/h2>
&lt;h3 id="31-dagscheduler调度器">3.1 DAGScheduler调度器&lt;/h3>
&lt;h4 id="dagscheduler作业提交流程图">DAGScheduler作业提交流程图&lt;/h4>
&lt;div class="mermaid">graph TD
A[用户调用Action] --> B[SparkContext.runJob]
B --> C[DAGScheduler.runJob]
C --> D[创建ActiveJob]
D --> E[submitJob]
E --> F[构建DAG图]
F --> G[findMissingPartitions]
G --> H[getMissingParentStages]
H --> I{是否有父Stage}
I -->|有| J[递归提交父Stage]
I -->|无| K[submitMissingTasks]
J --> L[等待父Stage完成]
L --> K
K --> M[创建TaskSet]
M --> N[TaskScheduler.submitTasks]
N --> O[分发Task到Executor]
O --> P[Task执行完成]
P --> Q[Stage完成]
Q --> R[检查后续Stage]
R --> S[Job完成]
style A fill:#e1f5fe
style F fill:#fff3e0
style K fill:#e8f5e8
style S fill:#c8e6c9
&lt;/div>
&lt;h3 id="32-stage划分算法">3.2 Stage划分算法&lt;/h3>
&lt;h4 id="stage划分算法流程图">Stage划分算法流程图&lt;/h4>
&lt;div class="mermaid">graph TD
A[开始Stage划分] --> B[从最终RDD开始]
B --> C[遍历RDD依赖]
C --> D{依赖类型}
D -->|窄依赖| E[加入当前Stage]
D -->|宽依赖| F[创建新Stage边界]
E --> G[继续遍历父RDD]
F --> H[创建ShuffleMapStage]
G --> C
H --> I[递归处理父RDD]
I --> C
C --> J{是否还有未处理RDD}
J -->|是| C
J -->|否| K[Stage划分完成]
style A fill:#e1f5fe
style F fill:#ffebee
style H fill:#fff3e0
style K fill:#e8f5e8
&lt;/div>
&lt;h4 id="dagscheduler源码分析">DAGScheduler源码分析&lt;/h4>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-scala" data-lang="scala">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">// DAGScheduler.scala 核心调度逻辑
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>&lt;span style="color:#66d9ef">class&lt;/span> &lt;span style="color:#a6e22e">DAGScheduler&lt;/span>&lt;span style="color:#f92672">(&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">private&lt;/span>&lt;span style="color:#f92672">[&lt;/span>&lt;span style="color:#66d9ef">scheduler&lt;/span>&lt;span style="color:#f92672">]&lt;/span> &lt;span style="color:#66d9ef">val&lt;/span> sc&lt;span style="color:#66d9ef">:&lt;/span> &lt;span style="color:#66d9ef">SparkContext&lt;/span>&lt;span style="color:#f92672">,&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">private&lt;/span>&lt;span style="color:#f92672">[&lt;/span>&lt;span style="color:#66d9ef">scheduler&lt;/span>&lt;span style="color:#f92672">]&lt;/span> &lt;span style="color:#66d9ef">val&lt;/span> taskScheduler&lt;span style="color:#66d9ef">:&lt;/span> &lt;span style="color:#66d9ef">TaskScheduler&lt;/span>&lt;span style="color:#f92672">,&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> listenerBus&lt;span style="color:#66d9ef">:&lt;/span> &lt;span style="color:#66d9ef">LiveListenerBus&lt;/span>&lt;span style="color:#f92672">,&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> mapOutputTracker&lt;span style="color:#66d9ef">:&lt;/span> &lt;span style="color:#66d9ef">MapOutputTrackerMaster&lt;/span>&lt;span style="color:#f92672">,&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> blockManagerMaster&lt;span style="color:#66d9ef">:&lt;/span> &lt;span style="color:#66d9ef">BlockManagerMaster&lt;/span>&lt;span style="color:#f92672">,&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> env&lt;span style="color:#66d9ef">:&lt;/span> &lt;span style="color:#66d9ef">SparkEnv&lt;/span>&lt;span style="color:#f92672">,&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> clock&lt;span style="color:#66d9ef">:&lt;/span> &lt;span style="color:#66d9ef">Clock&lt;/span> &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#66d9ef">new&lt;/span> &lt;span style="color:#a6e22e">SystemClock&lt;/span>&lt;span style="color:#f92672">())&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">extends&lt;/span> &lt;span style="color:#a6e22e">Logging&lt;/span> &lt;span style="color:#f92672">{&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e">// 事件处理循环
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span> &lt;span style="color:#66d9ef">private&lt;/span> &lt;span style="color:#66d9ef">val&lt;/span> eventProcessLoop &lt;span style="color:#66d9ef">=&lt;/span> &lt;span style="color:#66d9ef">new&lt;/span> &lt;span style="color:#a6e22e">DAGSchedulerEventProcessLoop&lt;/span>&lt;span style="color:#f92672">(&lt;/span>&lt;span style="color:#66d9ef">this&lt;/span>&lt;span style="color:#f92672">)&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e">// 提交作业的核心方法
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span> &lt;span style="color:#66d9ef">def&lt;/span> runJob&lt;span style="color:#f92672">[&lt;/span>&lt;span style="color:#66d9ef">T&lt;/span>, &lt;span style="color:#66d9ef">U&lt;/span>&lt;span style="color:#f92672">](&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> rdd&lt;span style="color:#66d9ef">:&lt;/span> &lt;span style="color:#66d9ef">RDD&lt;/span>&lt;span style="color:#f92672">[&lt;/span>&lt;span style="color:#66d9ef">T&lt;/span>&lt;span style="color:#f92672">],&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> func&lt;span style="color:#66d9ef">:&lt;/span> &lt;span style="color:#f92672">(&lt;/span>&lt;span style="color:#66d9ef">TaskContext&lt;/span>&lt;span style="color:#f92672">,&lt;/span> &lt;span style="color:#66d9ef">Iterator&lt;/span>&lt;span style="color:#f92672">[&lt;/span>&lt;span style="color:#66d9ef">T&lt;/span>&lt;span style="color:#f92672">])&lt;/span> &lt;span style="color:#66d9ef">=&amp;gt;&lt;/span> U&lt;span style="color:#f92672">,&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> partitions&lt;span style="color:#66d9ef">:&lt;/span> &lt;span style="color:#66d9ef">Seq&lt;/span>&lt;span style="color:#f92672">[&lt;/span>&lt;span style="color:#66d9ef">Int&lt;/span>&lt;span style="color:#f92672">],&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> callSite&lt;span style="color:#66d9ef">:&lt;/span> &lt;span style="color:#66d9ef">CallSite&lt;/span>&lt;span style="color:#f92672">,&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> resultHandler&lt;span style="color:#66d9ef">:&lt;/span> &lt;span style="color:#f92672">(&lt;/span>&lt;span style="color:#66d9ef">Int&lt;/span>&lt;span style="color:#f92672">,&lt;/span> &lt;span style="color:#66d9ef">U&lt;/span>&lt;span style="color:#f92672">)&lt;/span> &lt;span style="color:#66d9ef">=&amp;gt;&lt;/span> &lt;span style="color:#a6e22e">Unit&lt;/span>&lt;span style="color:#f92672">,&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> properties&lt;span style="color:#66d9ef">:&lt;/span> &lt;span style="color:#66d9ef">Properties&lt;/span>&lt;span style="color:#f92672">)&lt;/span>&lt;span style="color:#66d9ef">:&lt;/span> &lt;span style="color:#66d9ef">Unit&lt;/span> &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#f92672">{&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">val&lt;/span> start &lt;span style="color:#66d9ef">=&lt;/span> &lt;span style="color:#a6e22e">System&lt;/span>&lt;span style="color:#f92672">.&lt;/span>nanoTime
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">val&lt;/span> waiter &lt;span style="color:#66d9ef">=&lt;/span> submitJob&lt;span style="color:#f92672">(&lt;/span>rdd&lt;span style="color:#f92672">,&lt;/span> func&lt;span style="color:#f92672">,&lt;/span> partitions&lt;span style="color:#f92672">,&lt;/span> callSite&lt;span style="color:#f92672">,&lt;/span> resultHandler&lt;span style="color:#f92672">,&lt;/span> properties&lt;span style="color:#f92672">)&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">ThreadUtils&lt;/span>&lt;span style="color:#f92672">.&lt;/span>awaitReady&lt;span style="color:#f92672">(&lt;/span>waiter&lt;span style="color:#f92672">,&lt;/span> &lt;span style="color:#a6e22e">Duration&lt;/span>&lt;span style="color:#f92672">.&lt;/span>&lt;span style="color:#a6e22e">Inf&lt;/span>&lt;span style="color:#f92672">)&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> waiter&lt;span style="color:#f92672">.&lt;/span>value&lt;span style="color:#f92672">.&lt;/span>get &lt;span style="color:#66d9ef">match&lt;/span> &lt;span style="color:#f92672">{&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">case&lt;/span> scala&lt;span style="color:#f92672">.&lt;/span>util&lt;span style="color:#f92672">.&lt;/span>&lt;span style="color:#a6e22e">Success&lt;/span>&lt;span style="color:#f92672">(&lt;/span>&lt;span style="color:#66d9ef">_&lt;/span>&lt;span style="color:#f92672">)&lt;/span> &lt;span style="color:#66d9ef">=&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> logInfo&lt;span style="color:#f92672">(&lt;/span>&lt;span style="color:#e6db74">&amp;#34;Job %d finished: %s, took %f s&amp;#34;&lt;/span>&lt;span style="color:#f92672">.&lt;/span>format
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">(&lt;/span>waiter&lt;span style="color:#f92672">.&lt;/span>jobId&lt;span style="color:#f92672">,&lt;/span> callSite&lt;span style="color:#f92672">.&lt;/span>shortForm&lt;span style="color:#f92672">,&lt;/span> &lt;span style="color:#f92672">(&lt;/span>&lt;span style="color:#a6e22e">System&lt;/span>&lt;span style="color:#f92672">.&lt;/span>nanoTime &lt;span style="color:#f92672">-&lt;/span> start&lt;span style="color:#f92672">)&lt;/span> &lt;span style="color:#f92672">/&lt;/span> &lt;span style="color:#ae81ff">1&lt;/span>e9&lt;span style="color:#f92672">))&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">case&lt;/span> scala&lt;span style="color:#f92672">.&lt;/span>util&lt;span style="color:#f92672">.&lt;/span>&lt;span style="color:#a6e22e">Failure&lt;/span>&lt;span style="color:#f92672">(&lt;/span>exception&lt;span style="color:#f92672">)&lt;/span> &lt;span style="color:#66d9ef">=&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> logInfo&lt;span style="color:#f92672">(&lt;/span>&lt;span style="color:#e6db74">&amp;#34;Job %d failed: %s, took %f s&amp;#34;&lt;/span>&lt;span style="color:#f92672">.&lt;/span>format
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">(&lt;/span>waiter&lt;span style="color:#f92672">.&lt;/span>jobId&lt;span style="color:#f92672">,&lt;/span> callSite&lt;span style="color:#f92672">.&lt;/span>shortForm&lt;span style="color:#f92672">,&lt;/span> &lt;span style="color:#f92672">(&lt;/span>&lt;span style="color:#a6e22e">System&lt;/span>&lt;span style="color:#f92672">.&lt;/span>nanoTime &lt;span style="color:#f92672">-&lt;/span> start&lt;span style="color:#f92672">)&lt;/span> &lt;span style="color:#f92672">/&lt;/span> &lt;span style="color:#ae81ff">1&lt;/span>e9&lt;span style="color:#f92672">))&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">throw&lt;/span> exception
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">}&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">}&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e">// Stage划分核心算法
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span> &lt;span style="color:#66d9ef">private&lt;/span> &lt;span style="color:#66d9ef">def&lt;/span> getOrCreateShuffleMapStage&lt;span style="color:#f92672">(&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> shuffleDep&lt;span style="color:#66d9ef">:&lt;/span> &lt;span style="color:#66d9ef">ShuffleDependency&lt;/span>&lt;span style="color:#f92672">[&lt;/span>&lt;span style="color:#66d9ef">_&lt;/span>, &lt;span style="color:#66d9ef">_&lt;/span>, &lt;span style="color:#66d9ef">_&lt;/span>&lt;span style="color:#f92672">],&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> firstJobId&lt;span style="color:#66d9ef">:&lt;/span> &lt;span style="color:#66d9ef">Int&lt;/span>&lt;span style="color:#f92672">)&lt;/span>&lt;span style="color:#66d9ef">:&lt;/span> &lt;span style="color:#66d9ef">ShuffleMapStage&lt;/span> &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#f92672">{&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> shuffleIdToMapStage&lt;span style="color:#f92672">.&lt;/span>get&lt;span style="color:#f92672">(&lt;/span>shuffleDep&lt;span style="color:#f92672">.&lt;/span>shuffleId&lt;span style="color:#f92672">)&lt;/span> &lt;span style="color:#66d9ef">match&lt;/span> &lt;span style="color:#f92672">{&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">case&lt;/span> &lt;span style="color:#a6e22e">Some&lt;/span>&lt;span style="color:#f92672">(&lt;/span>stage&lt;span style="color:#f92672">)&lt;/span> &lt;span style="color:#66d9ef">=&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> stage
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">case&lt;/span> &lt;span style="color:#a6e22e">None&lt;/span> &lt;span style="color:#66d9ef">=&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e">// 递归创建父Stage
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span> getMissingAncestorShuffleDependencies&lt;span style="color:#f92672">(&lt;/span>shuffleDep&lt;span style="color:#f92672">.&lt;/span>rdd&lt;span style="color:#f92672">).&lt;/span>foreach &lt;span style="color:#f92672">{&lt;/span> dep &lt;span style="color:#66d9ef">=&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">if&lt;/span> &lt;span style="color:#f92672">(!&lt;/span>shuffleIdToMapStage&lt;span style="color:#f92672">.&lt;/span>contains&lt;span style="color:#f92672">(&lt;/span>dep&lt;span style="color:#f92672">.&lt;/span>shuffleId&lt;span style="color:#f92672">))&lt;/span> &lt;span style="color:#f92672">{&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> createShuffleMapStage&lt;span style="color:#f92672">(&lt;/span>dep&lt;span style="color:#f92672">,&lt;/span> firstJobId&lt;span style="color:#f92672">)&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">}&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">}&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> createShuffleMapStage&lt;span style="color:#f92672">(&lt;/span>shuffleDep&lt;span style="color:#f92672">,&lt;/span> firstJobId&lt;span style="color:#f92672">)&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">}&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">}&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e">// 查找缺失的父依赖
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span> &lt;span style="color:#66d9ef">private&lt;/span> &lt;span style="color:#66d9ef">def&lt;/span> getMissingAncestorShuffleDependencies&lt;span style="color:#f92672">(&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> rdd&lt;span style="color:#66d9ef">:&lt;/span> &lt;span style="color:#66d9ef">RDD&lt;/span>&lt;span style="color:#f92672">[&lt;/span>&lt;span style="color:#66d9ef">_&lt;/span>&lt;span style="color:#f92672">])&lt;/span>&lt;span style="color:#66d9ef">:&lt;/span> &lt;span style="color:#66d9ef">ArrayStack&lt;/span>&lt;span style="color:#f92672">[&lt;/span>&lt;span style="color:#66d9ef">ShuffleDependency&lt;/span>&lt;span style="color:#f92672">[&lt;/span>&lt;span style="color:#66d9ef">_&lt;/span>, &lt;span style="color:#66d9ef">_&lt;/span>, &lt;span style="color:#66d9ef">_&lt;/span>&lt;span style="color:#f92672">]]&lt;/span> &lt;span style="color:#66d9ef">=&lt;/span> &lt;span style="color:#f92672">{&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">val&lt;/span> ancestors &lt;span style="color:#66d9ef">=&lt;/span> &lt;span style="color:#66d9ef">new&lt;/span> &lt;span style="color:#a6e22e">ArrayStack&lt;/span>&lt;span style="color:#f92672">[&lt;/span>&lt;span style="color:#66d9ef">ShuffleDependency&lt;/span>&lt;span style="color:#f92672">[&lt;/span>&lt;span style="color:#66d9ef">_&lt;/span>, &lt;span style="color:#66d9ef">_&lt;/span>, &lt;span style="color:#66d9ef">_&lt;/span>&lt;span style="color:#f92672">]]&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">val&lt;/span> visited &lt;span style="color:#66d9ef">=&lt;/span> &lt;span style="color:#66d9ef">new&lt;/span> &lt;span style="color:#a6e22e">HashSet&lt;/span>&lt;span style="color:#f92672">[&lt;/span>&lt;span style="color:#66d9ef">RDD&lt;/span>&lt;span style="color:#f92672">[&lt;/span>&lt;span style="color:#66d9ef">_&lt;/span>&lt;span style="color:#f92672">]]&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">val&lt;/span> waitingForVisit &lt;span style="color:#66d9ef">=&lt;/span> &lt;span style="color:#66d9ef">new&lt;/span> &lt;span style="color:#a6e22e">ArrayStack&lt;/span>&lt;span style="color:#f92672">[&lt;/span>&lt;span style="color:#66d9ef">RDD&lt;/span>&lt;span style="color:#f92672">[&lt;/span>&lt;span style="color:#66d9ef">_&lt;/span>&lt;span style="color:#f92672">]]&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> waitingForVisit&lt;span style="color:#f92672">.&lt;/span>push&lt;span style="color:#f92672">(&lt;/span>rdd&lt;span style="color:#f92672">)&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">while&lt;/span> &lt;span style="color:#f92672">(&lt;/span>waitingForVisit&lt;span style="color:#f92672">.&lt;/span>nonEmpty&lt;span style="color:#f92672">)&lt;/span> &lt;span style="color:#f92672">{&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">val&lt;/span> toVisit &lt;span style="color:#66d9ef">=&lt;/span> waitingForVisit&lt;span style="color:#f92672">.&lt;/span>pop&lt;span style="color:#f92672">()&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">if&lt;/span> &lt;span style="color:#f92672">(!&lt;/span>visited&lt;span style="color:#f92672">(&lt;/span>toVisit&lt;span style="color:#f92672">))&lt;/span> &lt;span style="color:#f92672">{&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> visited &lt;span style="color:#f92672">+=&lt;/span> toVisit
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> toVisit&lt;span style="color:#f92672">.&lt;/span>dependencies&lt;span style="color:#f92672">.&lt;/span>foreach &lt;span style="color:#f92672">{&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">case&lt;/span> shuffleDep&lt;span style="color:#66d9ef">:&lt;/span> &lt;span style="color:#66d9ef">ShuffleDependency&lt;/span>&lt;span style="color:#f92672">[&lt;/span>&lt;span style="color:#66d9ef">_&lt;/span>, &lt;span style="color:#66d9ef">_&lt;/span>, &lt;span style="color:#66d9ef">_&lt;/span>&lt;span style="color:#f92672">]&lt;/span> &lt;span style="color:#66d9ef">=&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">if&lt;/span> &lt;span style="color:#f92672">(!&lt;/span>shuffleIdToMapStage&lt;span style="color:#f92672">.&lt;/span>contains&lt;span style="color:#f92672">(&lt;/span>shuffleDep&lt;span style="color:#f92672">.&lt;/span>shuffleId&lt;span style="color:#f92672">))&lt;/span> &lt;span style="color:#f92672">{&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> ancestors&lt;span style="color:#f92672">.&lt;/span>push&lt;span style="color:#f92672">(&lt;/span>shuffleDep&lt;span style="color:#f92672">)&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> waitingForVisit&lt;span style="color:#f92672">.&lt;/span>push&lt;span style="color:#f92672">(&lt;/span>shuffleDep&lt;span style="color:#f92672">.&lt;/span>rdd&lt;span style="color:#f92672">)&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">}&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">case&lt;/span> narrowDep&lt;span style="color:#66d9ef">:&lt;/span> &lt;span style="color:#66d9ef">NarrowDependency&lt;/span>&lt;span style="color:#f92672">[&lt;/span>&lt;span style="color:#66d9ef">_&lt;/span>&lt;span style="color:#f92672">]&lt;/span> &lt;span style="color:#66d9ef">=&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> waitingForVisit&lt;span style="color:#f92672">.&lt;/span>push&lt;span style="color:#f92672">(&lt;/span>narrowDep&lt;span style="color:#f92672">.&lt;/span>rdd&lt;span style="color:#f92672">)&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">}&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">}&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">}&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> ancestors
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">}&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e">// 提交Stage
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span> &lt;span style="color:#66d9ef">private&lt;/span> &lt;span style="color:#66d9ef">def&lt;/span> submitStage&lt;span style="color:#f92672">(&lt;/span>stage&lt;span style="color:#66d9ef">:&lt;/span> &lt;span style="color:#66d9ef">Stage&lt;/span>&lt;span style="color:#f92672">)&lt;/span>&lt;span style="color:#66d9ef">:&lt;/span> &lt;span style="color:#66d9ef">Unit&lt;/span> &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#f92672">{&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">val&lt;/span> jobId &lt;span style="color:#66d9ef">=&lt;/span> activeJobForStage&lt;span style="color:#f92672">(&lt;/span>stage&lt;span style="color:#f92672">)&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">if&lt;/span> &lt;span style="color:#f92672">(&lt;/span>jobId&lt;span style="color:#f92672">.&lt;/span>isDefined&lt;span style="color:#f92672">)&lt;/span> &lt;span style="color:#f92672">{&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">if&lt;/span> &lt;span style="color:#f92672">(!&lt;/span>waitingStages&lt;span style="color:#f92672">(&lt;/span>stage&lt;span style="color:#f92672">)&lt;/span> &lt;span style="color:#f92672">&amp;amp;&amp;amp;&lt;/span> &lt;span style="color:#f92672">!&lt;/span>runningStages&lt;span style="color:#f92672">(&lt;/span>stage&lt;span style="color:#f92672">)&lt;/span> &lt;span style="color:#f92672">&amp;amp;&amp;amp;&lt;/span> &lt;span style="color:#f92672">!&lt;/span>failedStages&lt;span style="color:#f92672">(&lt;/span>stage&lt;span style="color:#f92672">))&lt;/span> &lt;span style="color:#f92672">{&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">val&lt;/span> missing &lt;span style="color:#66d9ef">=&lt;/span> getMissingParentStages&lt;span style="color:#f92672">(&lt;/span>stage&lt;span style="color:#f92672">).&lt;/span>sortBy&lt;span style="color:#f92672">(&lt;/span>&lt;span style="color:#66d9ef">_&lt;/span>&lt;span style="color:#f92672">.&lt;/span>id&lt;span style="color:#f92672">)&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">if&lt;/span> &lt;span style="color:#f92672">(&lt;/span>missing&lt;span style="color:#f92672">.&lt;/span>isEmpty&lt;span style="color:#f92672">)&lt;/span> &lt;span style="color:#f92672">{&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> submitMissingTasks&lt;span style="color:#f92672">(&lt;/span>stage&lt;span style="color:#f92672">,&lt;/span> jobId&lt;span style="color:#f92672">.&lt;/span>get&lt;span style="color:#f92672">)&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">}&lt;/span> &lt;span style="color:#66d9ef">else&lt;/span> &lt;span style="color:#f92672">{&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">for&lt;/span> &lt;span style="color:#f92672">(&lt;/span>parent &lt;span style="color:#66d9ef">&amp;lt;-&lt;/span> missing&lt;span style="color:#f92672">)&lt;/span> &lt;span style="color:#f92672">{&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> submitStage&lt;span style="color:#f92672">(&lt;/span>parent&lt;span style="color:#f92672">)&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">}&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> waitingStages &lt;span style="color:#f92672">+=&lt;/span> stage
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">}&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">}&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">}&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">}&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f92672">}&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h3 id="33-内存监控与优化">3.3 内存监控与优化&lt;/h3>
&lt;h4 id="内存存储状态监控">内存存储状态监控&lt;/h4>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-scala" data-lang="scala">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">// 内存使用监控组件
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>&lt;span style="color:#66d9ef">class&lt;/span> &lt;span style="color:#a6e22e">MemoryMonitor&lt;/span> &lt;span style="color:#f92672">{&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e">// 监控Map的内存使用
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span> &lt;span style="color:#66d9ef">def&lt;/span> monitorMapMemory&lt;span style="color:#f92672">(&lt;/span>map&lt;span style="color:#66d9ef">:&lt;/span> &lt;span style="color:#66d9ef">SizeTrackingAppendOnlyMap&lt;/span>&lt;span style="color:#f92672">[&lt;/span>&lt;span style="color:#66d9ef">_&lt;/span>, &lt;span style="color:#66d9ef">_&lt;/span>&lt;span style="color:#f92672">])&lt;/span>&lt;span style="color:#66d9ef">:&lt;/span> &lt;span style="color:#66d9ef">MemoryUsage&lt;/span> &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#f92672">{&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">val&lt;/span> estimatedSize &lt;span style="color:#66d9ef">=&lt;/span> map&lt;span style="color:#f92672">.&lt;/span>estimateSize&lt;span style="color:#f92672">()&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">val&lt;/span> currentMemory &lt;span style="color:#66d9ef">=&lt;/span> map&lt;span style="color:#f92672">.&lt;/span>currentMemory
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">val&lt;/span> maxMemory &lt;span style="color:#66d9ef">=&lt;/span> map&lt;span style="color:#f92672">.&lt;/span>maxMemory
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">MemoryUsage&lt;/span>&lt;span style="color:#f92672">(&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> estimatedSize &lt;span style="color:#66d9ef">=&lt;/span> estimatedSize&lt;span style="color:#f92672">,&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> currentMemory &lt;span style="color:#66d9ef">=&lt;/span> currentMemory&lt;span style="color:#f92672">,&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> maxMemory &lt;span style="color:#66d9ef">=&lt;/span> maxMemory&lt;span style="color:#f92672">,&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> utilization &lt;span style="color:#66d9ef">=&lt;/span> currentMemory&lt;span style="color:#f92672">.&lt;/span>toDouble &lt;span style="color:#f92672">/&lt;/span> maxMemory
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">)&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">}&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e">// 监控Spill状态
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span> &lt;span style="color:#66d9ef">def&lt;/span> monitorSpillStatus&lt;span style="color:#f92672">(&lt;/span>externalMap&lt;span style="color:#66d9ef">:&lt;/span> &lt;span style="color:#66d9ef">ExternalAppendOnlyMap&lt;/span>&lt;span style="color:#f92672">[&lt;/span>&lt;span style="color:#66d9ef">_&lt;/span>, &lt;span style="color:#66d9ef">_&lt;/span>, &lt;span style="color:#66d9ef">_&lt;/span>&lt;span style="color:#f92672">])&lt;/span>&lt;span style="color:#66d9ef">:&lt;/span> &lt;span style="color:#66d9ef">SpillStatus&lt;/span> &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#f92672">{&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">val&lt;/span> spillCount &lt;span style="color:#66d9ef">=&lt;/span> externalMap&lt;span style="color:#f92672">.&lt;/span>spills&lt;span style="color:#f92672">.&lt;/span>size
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">val&lt;/span> totalSpillSize &lt;span style="color:#66d9ef">=&lt;/span> externalMap&lt;span style="color:#f92672">.&lt;/span>spills&lt;span style="color:#f92672">.&lt;/span>map&lt;span style="color:#f92672">(&lt;/span>&lt;span style="color:#66d9ef">_&lt;/span>&lt;span style="color:#f92672">.&lt;/span>size&lt;span style="color:#f92672">).&lt;/span>sum
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">SpillStatus&lt;/span>&lt;span style="color:#f92672">(&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> spillCount &lt;span style="color:#66d9ef">=&lt;/span> spillCount&lt;span style="color:#f92672">,&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> totalSpillSize &lt;span style="color:#66d9ef">=&lt;/span> totalSpillSize&lt;span style="color:#f92672">,&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> averageSpillSize &lt;span style="color:#66d9ef">=&lt;/span> &lt;span style="color:#66d9ef">if&lt;/span> &lt;span style="color:#f92672">(&lt;/span>spillCount &lt;span style="color:#f92672">&amp;gt;&lt;/span> &lt;span style="color:#ae81ff">0&lt;/span>&lt;span style="color:#f92672">)&lt;/span> totalSpillSize &lt;span style="color:#f92672">/&lt;/span> spillCount &lt;span style="color:#66d9ef">else&lt;/span> &lt;span style="color:#ae81ff">0&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">)&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">}&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f92672">}&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">case&lt;/span> &lt;span style="color:#66d9ef">class&lt;/span> &lt;span style="color:#a6e22e">MemoryUsage&lt;/span>&lt;span style="color:#f92672">(&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> estimatedSize&lt;span style="color:#66d9ef">:&lt;/span> &lt;span style="color:#66d9ef">Long&lt;/span>&lt;span style="color:#f92672">,&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> currentMemory&lt;span style="color:#66d9ef">:&lt;/span> &lt;span style="color:#66d9ef">Long&lt;/span>&lt;span style="color:#f92672">,&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> maxMemory&lt;span style="color:#66d9ef">:&lt;/span> &lt;span style="color:#66d9ef">Long&lt;/span>&lt;span style="color:#f92672">,&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> utilization&lt;span style="color:#66d9ef">:&lt;/span> &lt;span style="color:#66d9ef">Double&lt;/span>&lt;span style="color:#f92672">)&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">case&lt;/span> &lt;span style="color:#66d9ef">class&lt;/span> &lt;span style="color:#a6e22e">SpillStatus&lt;/span>&lt;span style="color:#f92672">(&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> spillCount&lt;span style="color:#66d9ef">:&lt;/span> &lt;span style="color:#66d9ef">Int&lt;/span>&lt;span style="color:#f92672">,&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> totalSpillSize&lt;span style="color:#66d9ef">:&lt;/span> &lt;span style="color:#66d9ef">Long&lt;/span>&lt;span style="color:#f92672">,&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> averageSpillSize&lt;span style="color:#66d9ef">:&lt;/span> &lt;span style="color:#66d9ef">Long&lt;/span>&lt;span style="color:#f92672">)&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h4 id="内存存储监控流程图">内存存储监控流程图&lt;/h4>
&lt;div class="mermaid">graph TD
A[输入数据] --> B[PartitionedAppendOnlyMap]
B --> C{内存是否足够?}
C -->|是| D[内存聚合]
C -->|否| E[Spill到磁盘]
D --> F[返回结果]
E --> G[ExternalAppendOnlyMap]
G --> H[合并内存和磁盘数据]
H --> F
I[MemoryMonitor] --> B
I --> G
J[SpillMonitor] --> E
&lt;/div>
&lt;h4 id="内存存储优化策略">内存存储优化策略&lt;/h4>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-scala" data-lang="scala">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">// 内存分配优化
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>&lt;span style="color:#66d9ef">class&lt;/span> &lt;span style="color:#a6e22e">MemoryOptimizer&lt;/span> &lt;span style="color:#f92672">{&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e">// 动态调整内存阈值
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span> &lt;span style="color:#66d9ef">def&lt;/span> adjustMemoryThreshold&lt;span style="color:#f92672">(&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> currentMemory&lt;span style="color:#66d9ef">:&lt;/span> &lt;span style="color:#66d9ef">Long&lt;/span>&lt;span style="color:#f92672">,&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> maxMemory&lt;span style="color:#66d9ef">:&lt;/span> &lt;span style="color:#66d9ef">Long&lt;/span>&lt;span style="color:#f92672">,&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> spillCount&lt;span style="color:#66d9ef">:&lt;/span> &lt;span style="color:#66d9ef">Int&lt;/span>&lt;span style="color:#f92672">)&lt;/span>&lt;span style="color:#66d9ef">:&lt;/span> &lt;span style="color:#66d9ef">Long&lt;/span> &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#f92672">{&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">val&lt;/span> utilization &lt;span style="color:#66d9ef">=&lt;/span> currentMemory&lt;span style="color:#f92672">.&lt;/span>toDouble &lt;span style="color:#f92672">/&lt;/span> maxMemory
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">if&lt;/span> &lt;span style="color:#f92672">(&lt;/span>utilization &lt;span style="color:#f92672">&amp;gt;&lt;/span> &lt;span style="color:#ae81ff">0.8&lt;/span> &lt;span style="color:#f92672">&amp;amp;&amp;amp;&lt;/span> spillCount &lt;span style="color:#f92672">&amp;gt;&lt;/span> &lt;span style="color:#ae81ff">0&lt;/span>&lt;span style="color:#f92672">)&lt;/span> &lt;span style="color:#f92672">{&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e">// 内存使用率高且有Spill，降低阈值
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span> &lt;span style="color:#f92672">(&lt;/span>maxMemory &lt;span style="color:#f92672">*&lt;/span> &lt;span style="color:#ae81ff">0.6&lt;/span>&lt;span style="color:#f92672">).&lt;/span>toLong
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">}&lt;/span> &lt;span style="color:#66d9ef">else&lt;/span> &lt;span style="color:#66d9ef">if&lt;/span> &lt;span style="color:#f92672">(&lt;/span>utilization &lt;span style="color:#f92672">&amp;lt;&lt;/span> &lt;span style="color:#ae81ff">0.5&lt;/span> &lt;span style="color:#f92672">&amp;amp;&amp;amp;&lt;/span> spillCount &lt;span style="color:#f92672">==&lt;/span> &lt;span style="color:#ae81ff">0&lt;/span>&lt;span style="color:#f92672">)&lt;/span> &lt;span style="color:#f92672">{&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e">// 内存使用率低且无Spill，提高阈值
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span> &lt;span style="color:#f92672">(&lt;/span>maxMemory &lt;span style="color:#f92672">*&lt;/span> &lt;span style="color:#ae81ff">0.9&lt;/span>&lt;span style="color:#f92672">).&lt;/span>toLong
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">}&lt;/span> &lt;span style="color:#66d9ef">else&lt;/span> &lt;span style="color:#f92672">{&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e">// 保持当前阈值
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span> &lt;span style="color:#f92672">(&lt;/span>maxMemory &lt;span style="color:#f92672">*&lt;/span> &lt;span style="color:#ae81ff">0.8&lt;/span>&lt;span style="color:#f92672">).&lt;/span>toLong
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">}&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">}&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e">// 优化Map初始容量
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span> &lt;span style="color:#66d9ef">def&lt;/span> optimizeInitialCapacity&lt;span style="color:#f92672">(&lt;/span>dataSize&lt;span style="color:#66d9ef">:&lt;/span> &lt;span style="color:#66d9ef">Long&lt;/span>&lt;span style="color:#f92672">)&lt;/span>&lt;span style="color:#66d9ef">:&lt;/span> &lt;span style="color:#66d9ef">Int&lt;/span> &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#f92672">{&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">val&lt;/span> estimatedSize &lt;span style="color:#66d9ef">=&lt;/span> &lt;span style="color:#f92672">(&lt;/span>dataSize &lt;span style="color:#f92672">*&lt;/span> &lt;span style="color:#ae81ff">1.2&lt;/span>&lt;span style="color:#f92672">).&lt;/span>toInt
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> math&lt;span style="color:#f92672">.&lt;/span>max&lt;span style="color:#f92672">(&lt;/span>&lt;span style="color:#ae81ff">64&lt;/span>&lt;span style="color:#f92672">,&lt;/span> math&lt;span style="color:#f92672">.&lt;/span>min&lt;span style="color:#f92672">(&lt;/span>estimatedSize&lt;span style="color:#f92672">,&lt;/span> &lt;span style="color:#ae81ff">1024&lt;/span> &lt;span style="color:#f92672">*&lt;/span> &lt;span style="color:#ae81ff">1024&lt;/span>&lt;span style="color:#f92672">))&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">}&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f92672">}&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;hr>
&lt;h3 id="34-taskscheduler任务调度">3.4 TaskScheduler任务调度&lt;/h3>
&lt;h4 id="dag的生成与依赖分析">DAG的生成与依赖分析&lt;/h4>
&lt;p>&lt;strong>任务提交完整流程图&lt;/strong>：&lt;/p></description></item><item><title>21.1.flink源码解析</title><link>https://pothos.dpdns.org/posts/21.1.flink%E6%BA%90%E7%A0%81%E8%A7%A3%E6%9E%90/</link><pubDate>Thu, 25 Dec 2025 00:00:00 +0000</pubDate><guid>https://pothos.dpdns.org/posts/21.1.flink%E6%BA%90%E7%A0%81%E8%A7%A3%E6%9E%90/</guid><description>&lt;h1 id="211-flink源码解析">21.1 Flink源码解析&lt;/h1>
&lt;h2 id="目录">目录&lt;/h2>
&lt;details>
&lt;summary>点击展开目录&lt;/summary>
&lt;h3 id="一flink核心架构与初始化">一、Flink核心架构与初始化&lt;/h3>
&lt;ul>
&lt;li>&lt;a href="#11-flink%E8%BF%90%E8%A1%8C%E6%97%B6%E6%9E%B6%E6%9E%84">1.1 Flink运行时架构&lt;/a>&lt;/li>
&lt;li>&lt;a href="#12-jobmanager%E5%90%AF%E5%8A%A8%E6%B5%81%E7%A8%8B">1.2 JobManager启动流程&lt;/a>&lt;/li>
&lt;li>&lt;a href="#13-taskmanager%E5%90%AF%E5%8A%A8%E6%B5%81%E7%A8%8B">1.3 TaskManager启动流程&lt;/a>&lt;/li>
&lt;/ul>
&lt;h3 id="二作业图构建与优化">二、作业图构建与优化&lt;/h3>
&lt;ul>
&lt;li>&lt;a href="#21-streamgraph%E6%9E%84%E5%BB%BA">2.1 StreamGraph构建&lt;/a>&lt;/li>
&lt;li>&lt;a href="#22-jobgraph%E7%94%9F%E6%88%90">2.2 JobGraph生成&lt;/a>&lt;/li>
&lt;li>&lt;a href="#23-executiongraph%E5%88%9B%E5%BB%BA">2.3 ExecutionGraph创建&lt;/a>&lt;/li>
&lt;li>&lt;a href="#24-%E7%89%A9%E7%90%86%E5%9B%BE%E9%83%A8%E7%BD%B2">2.4 物理图部署&lt;/a>&lt;/li>
&lt;/ul>
&lt;h3 id="三任务调度系统">三、任务调度系统&lt;/h3>
&lt;ul>
&lt;li>&lt;a href="#31-%E8%B0%83%E5%BA%A6%E5%99%A8%E6%9E%B6%E6%9E%84">3.1 调度器架构&lt;/a>&lt;/li>
&lt;li>&lt;a href="#32-%E4%BB%BB%E5%8A%A1%E9%83%A8%E7%BD%B2%E6%B5%81%E7%A8%8B">3.2 任务部署流程&lt;/a>
&lt;ul>
&lt;li>&lt;a href="#flink%E5%AE%8C%E6%95%B4%E4%BD%9C%E4%B8%9A%E6%89%A7%E8%A1%8C%E6%97%B6%E5%BA%8F%E5%9B%BE">Flink完整作业执行时序图&lt;/a>&lt;/li>
&lt;li>&lt;a href="#%E8%AF%A6%E7%BB%86%E6%8A%80%E6%9C%AF%E5%AE%9E%E7%8E%B0%E6%97%B6%E5%BA%8F%E5%9B%BE">详细技术实现时序图&lt;/a>&lt;/li>
&lt;li>&lt;a href="#%E5%85%B3%E9%94%AE%E6%97%B6%E9%97%B4%E8%8A%82%E7%82%B9%E8%AF%B4%E6%98%8E">关键时间节点说明&lt;/a>&lt;/li>
&lt;li>&lt;a href="#flink-yarn%E6%A8%A1%E5%BC%8F%E5%AE%8C%E6%95%B4%E6%89%A7%E8%A1%8C%E6%97%B6%E5%BA%8F%E5%9B%BE">Flink YARN模式完整执行时序图&lt;/a>&lt;/li>
&lt;li>&lt;a href="#flink%E4%B8%8Espark-yarn%E6%A8%A1%E5%BC%8F%E5%AF%B9%E6%AF%94">Flink与Spark YARN模式对比&lt;/a>&lt;/li>
&lt;/ul>
&lt;/li>
&lt;li>&lt;a href="#33-%E8%B5%84%E6%BA%90%E5%88%86%E9%85%8D%E6%9C%BA%E5%88%B6">3.3 资源分配机制&lt;/a>&lt;/li>
&lt;li>&lt;a href="#34-%E6%95%85%E9%9A%9C%E6%81%A2%E5%A4%8D%E8%B0%83%E5%BA%A6">3.4 故障恢复调度&lt;/a>&lt;/li>
&lt;/ul>
&lt;h3 id="四内存管理系统">四、内存管理系统&lt;/h3>
&lt;ul>
&lt;li>&lt;a href="#41-%E5%86%85%E5%AD%98%E7%AE%A1%E7%90%86%E6%9E%B6%E6%9E%84">4.1 内存管理架构&lt;/a>&lt;/li>
&lt;li>&lt;a href="#42-%E7%BD%91%E7%BB%9C%E5%86%85%E5%AD%98%E7%AE%A1%E7%90%86">4.2 网络内存管理&lt;/a>&lt;/li>
&lt;li>&lt;a href="#43-%E5%A0%86%E5%A4%96%E5%86%85%E5%AD%98%E4%BD%BF%E7%94%A8">4.3 堆外内存使用&lt;/a>&lt;/li>
&lt;/ul>
&lt;h3 id="五状态管理机制">五、状态管理机制&lt;/h3>
&lt;ul>
&lt;li>&lt;a href="#51-%E7%8A%B6%E6%80%81%E5%AD%98%E5%82%A8%E6%9E%B6%E6%9E%84">5.1 状态存储架构&lt;/a>&lt;/li>
&lt;li>&lt;a href="#52-keyedstate%E5%AE%9E%E7%8E%B0">5.2 KeyedState实现&lt;/a>&lt;/li>
&lt;li>&lt;a href="#53-operatorstate%E5%AE%9E%E7%8E%B0">5.3 OperatorState实现&lt;/a>&lt;/li>
&lt;li>&lt;a href="#54-%E7%8A%B6%E6%80%81%E5%90%8E%E7%AB%AF%E8%AF%A6%E8%A7%A3">5.4 状态后端详解&lt;/a>&lt;/li>
&lt;/ul>
&lt;h3 id="六检查点机制">六、检查点机制&lt;/h3>
&lt;ul>
&lt;li>&lt;a href="#61-%E6%A3%80%E6%9F%A5%E7%82%B9%E5%8D%8F%E8%B0%83%E5%99%A8">6.1 检查点协调器&lt;/a>&lt;/li>
&lt;li>&lt;a href="#62-%E5%88%86%E5%B8%83%E5%BC%8F%E5%BF%AB%E7%85%A7%E7%AE%97%E6%B3%95">6.2 分布式快照算法&lt;/a>&lt;/li>
&lt;li>&lt;a href="#63-%E6%A3%80%E6%9F%A5%E7%82%B9%E5%AD%98%E5%82%A8">6.3 检查点存储&lt;/a>&lt;/li>
&lt;li>&lt;a href="#64-%E6%81%A2%E5%A4%8D%E6%9C%BA%E5%88%B6">6.4 恢复机制&lt;/a>&lt;/li>
&lt;/ul>
&lt;h3 id="七网络通信系统">七、网络通信系统&lt;/h3>
&lt;ul>
&lt;li>&lt;a href="#71-%E7%BD%91%E7%BB%9C%E6%A0%88%E6%9E%B6%E6%9E%84">7.1 网络栈架构&lt;/a>&lt;/li>
&lt;li>&lt;a href="#72-%E6%95%B0%E6%8D%AE%E4%BC%A0%E8%BE%93%E6%9C%BA%E5%88%B6">7.2 数据传输机制&lt;/a>&lt;/li>
&lt;li>&lt;a href="#73-%E8%83%8C%E5%8E%8B%E5%A4%84%E7%90%86">7.3 背压处理&lt;/a>&lt;/li>
&lt;li>&lt;a href="#74-%E7%BD%91%E7%BB%9C%E7%BC%93%E5%86%B2%E7%AE%A1%E7%90%86">7.4 网络缓冲管理&lt;/a>&lt;/li>
&lt;/ul>
&lt;h3 id="八时间与窗口机制">八、时间与窗口机制&lt;/h3>
&lt;ul>
&lt;li>&lt;a href="#81-%E6%97%B6%E9%97%B4%E8%AF%AD%E4%B9%89%E5%AE%9E%E7%8E%B0">8.1 时间语义实现&lt;/a>&lt;/li>
&lt;li>&lt;a href="#82-watermark%E6%9C%BA%E5%88%B6">8.2 Watermark机制&lt;/a>&lt;/li>
&lt;li>&lt;a href="#83-%E7%AA%97%E5%8F%A3%E7%AE%97%E5%AD%90%E5%AE%9E%E7%8E%B0">8.3 窗口算子实现&lt;/a>&lt;/li>
&lt;li>&lt;a href="#84-%E5%AE%9A%E6%97%B6%E5%99%A8%E6%9C%8D%E5%8A%A1">8.4 定时器服务&lt;/a>&lt;/li>
&lt;/ul>
&lt;h3 id="九容错与监控机制">九、容错与监控机制&lt;/h3>
&lt;ul>
&lt;li>&lt;a href="#91-%E5%BC%82%E5%B8%B8%E5%A4%84%E7%90%86%E6%9C%BA%E5%88%B6">9.1 异常处理机制&lt;/a>&lt;/li>
&lt;li>&lt;a href="#92-%E9%87%8D%E5%90%AF%E7%AD%96%E7%95%A5">9.2 重启策略&lt;/a>&lt;/li>
&lt;li>&lt;a href="#93-%E7%9B%91%E6%8E%A7%E6%8C%87%E6%A0%87%E7%B3%BB%E7%BB%9F">9.3 监控指标系统&lt;/a>&lt;/li>
&lt;/ul>
&lt;hr>
&lt;/details>
&lt;h2 id="一flink核心架构与初始化-1">一、Flink核心架构与初始化&lt;/h2>
&lt;h3 id="11-flink运行时架构">1.1 Flink运行时架构&lt;/h3>
&lt;h4 id="flink整体架构图">Flink整体架构图&lt;/h4>
&lt;div class="mermaid">graph TD
A[Client客户端] --> B[JobManager]
B --> C[ResourceManager]
B --> D[Dispatcher]
B --> E[JobMaster]
E --> F[TaskManager 1]
E --> G[TaskManager 2]
E --> H[TaskManager N]
F --> F1[Task Slot 1]
F --> F2[Task Slot 2]
G --> G1[Task Slot 1]
G --> G2[Task Slot 2]
H --> H1[Task Slot 1]
H --> H2[Task Slot 2]
I[Checkpoint Coordinator] --> E
J[State Backend] --> F
J --> G
J --> H
style A fill:#e1f5fe
style B fill:#fff3e0
style E fill:#e8f5e8
style I fill:#ffebee
&lt;/div>
&lt;h4 id="flink组件职责">Flink组件职责&lt;/h4>
&lt;table>
&lt;thead>
&lt;tr>
&lt;th>组件&lt;/th>
&lt;th>职责&lt;/th>
&lt;th>核心功能&lt;/th>
&lt;/tr>
&lt;/thead>
&lt;tbody>
&lt;tr>
&lt;td>&lt;strong>JobManager&lt;/strong>&lt;/td>
&lt;td>集群主节点&lt;/td>
&lt;td>作业调度、检查点协调、故障恢复&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;strong>TaskManager&lt;/strong>&lt;/td>
&lt;td>工作节点&lt;/td>
&lt;td>任务执行、数据缓存、网络通信&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;strong>ResourceManager&lt;/strong>&lt;/td>
&lt;td>资源管理&lt;/td>
&lt;td>资源分配、Slot管理&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;strong>Dispatcher&lt;/strong>&lt;/td>
&lt;td>作业分发&lt;/td>
&lt;td>接收作业、启动JobMaster&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;strong>JobMaster&lt;/strong>&lt;/td>
&lt;td>作业主控&lt;/td>
&lt;td>单个作业的调度和执行控制&lt;/td>
&lt;/tr>
&lt;/tbody>
&lt;/table>
&lt;h3 id="12-jobmanager启动流程">1.2 JobManager启动流程&lt;/h3>
&lt;h4 id="jobmanager启动流程图">JobManager启动流程图&lt;/h4>
&lt;div class="mermaid">graph TD
A[JobManager进程启动] --> B[创建ActorSystem]
B --> C[初始化ResourceManager]
C --> D[启动Dispatcher]
D --> E[启动WebUI服务]
E --> F[初始化HA服务]
F --> G[注册到服务发现]
G --> H[等待作业提交]
H --> I[接收作业提交]
I --> J[创建JobMaster]
J --> K[启动JobMaster]
K --> L[开始作业调度]
style A fill:#e1f5fe
style J fill:#fff3e0
style L fill:#e8f5e8
&lt;/div>
&lt;h4 id="jobmanager启动源码分析">JobManager启动源码分析&lt;/h4>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-scala" data-lang="scala">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">// JobManagerRunner.scala - JobManager启动入口
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>&lt;span style="color:#66d9ef">class&lt;/span> &lt;span style="color:#a6e22e">JobManagerRunner&lt;/span>&lt;span style="color:#f92672">(&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> jobGraph&lt;span style="color:#66d9ef">:&lt;/span> &lt;span style="color:#66d9ef">JobGraph&lt;/span>&lt;span style="color:#f92672">,&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> configuration&lt;span style="color:#66d9ef">:&lt;/span> &lt;span style="color:#66d9ef">Configuration&lt;/span>&lt;span style="color:#f92672">,&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> rpcService&lt;span style="color:#66d9ef">:&lt;/span> &lt;span style="color:#66d9ef">RpcService&lt;/span>&lt;span style="color:#f92672">,&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> resourceManagerGateway&lt;span style="color:#66d9ef">:&lt;/span> &lt;span style="color:#66d9ef">ResourceManagerGateway&lt;/span>&lt;span style="color:#f92672">)&lt;/span> &lt;span style="color:#f92672">{&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e">// JobMaster实例
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span> &lt;span style="color:#66d9ef">private&lt;/span> &lt;span style="color:#66d9ef">var&lt;/span> jobMaster&lt;span style="color:#66d9ef">:&lt;/span> &lt;span style="color:#66d9ef">JobMaster&lt;/span> &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#66d9ef">_&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">private&lt;/span> &lt;span style="color:#66d9ef">var&lt;/span> jobMasterGateway&lt;span style="color:#66d9ef">:&lt;/span> &lt;span style="color:#66d9ef">JobMasterGateway&lt;/span> &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#66d9ef">_&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e">// 启动JobMaster的核心方法
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span> &lt;span style="color:#66d9ef">def&lt;/span> start&lt;span style="color:#f92672">()&lt;/span>&lt;span style="color:#66d9ef">:&lt;/span> &lt;span style="color:#66d9ef">Unit&lt;/span> &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#f92672">{&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">try&lt;/span> &lt;span style="color:#f92672">{&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e">// 1. 创建JobMaster
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span> jobMaster &lt;span style="color:#66d9ef">=&lt;/span> &lt;span style="color:#66d9ef">new&lt;/span> &lt;span style="color:#a6e22e">JobMaster&lt;/span>&lt;span style="color:#f92672">(&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> rpcService&lt;span style="color:#f92672">,&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> jobGraph&lt;span style="color:#f92672">,&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> configuration&lt;span style="color:#f92672">,&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> resourceManagerGateway&lt;span style="color:#f92672">,&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> heartbeatServices&lt;span style="color:#f92672">,&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> scheduledExecutorService&lt;span style="color:#f92672">,&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> blobWriter&lt;span style="color:#f92672">,&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> highAvailabilityServices&lt;span style="color:#f92672">,&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> fatalErrorHandler&lt;span style="color:#f92672">)&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e">// 2. 启动JobMaster
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span> jobMaster&lt;span style="color:#f92672">.&lt;/span>start&lt;span style="color:#f92672">()&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e">// 3. 获取JobMaster网关
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span> &lt;span style="color:#66d9ef">val&lt;/span> timeout &lt;span style="color:#66d9ef">=&lt;/span> &lt;span style="color:#a6e22e">Time&lt;/span>&lt;span style="color:#f92672">.&lt;/span>fromDuration&lt;span style="color:#f92672">(&lt;/span>configuration&lt;span style="color:#f92672">.&lt;/span>get&lt;span style="color:#f92672">(&lt;/span>&lt;span style="color:#a6e22e">AkkaOptions&lt;/span>&lt;span style="color:#f92672">.&lt;/span>&lt;span style="color:#a6e22e">ASK_TIMEOUT&lt;/span>&lt;span style="color:#f92672">))&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> jobMasterGateway &lt;span style="color:#66d9ef">=&lt;/span> jobMaster&lt;span style="color:#f92672">.&lt;/span>getSelfGateway&lt;span style="color:#f92672">(&lt;/span>classOf&lt;span style="color:#f92672">[&lt;/span>&lt;span style="color:#66d9ef">JobMasterGateway&lt;/span>&lt;span style="color:#f92672">])&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e">// 4. 向ResourceManager注册
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span> registerJobMasterWithResourceManager&lt;span style="color:#f92672">()&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e">// 5. 开始调度执行图
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span> jobMaster&lt;span style="color:#f92672">.&lt;/span>scheduleExecutionGraph&lt;span style="color:#f92672">()&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> logInfo&lt;span style="color:#f92672">(&lt;/span>&lt;span style="color:#e6db74">s&amp;#34;Started JobMaster for job &lt;/span>&lt;span style="color:#e6db74">${&lt;/span>jobGraph&lt;span style="color:#f92672">.&lt;/span>getJobID&lt;span style="color:#e6db74">}&lt;/span>&lt;span style="color:#e6db74">&amp;#34;&lt;/span>&lt;span style="color:#f92672">)&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">}&lt;/span> &lt;span style="color:#66d9ef">catch&lt;/span> &lt;span style="color:#f92672">{&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">case&lt;/span> e&lt;span style="color:#66d9ef">:&lt;/span> &lt;span style="color:#66d9ef">Exception&lt;/span> &lt;span style="color:#f92672">=&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> logError&lt;span style="color:#f92672">(&lt;/span>&lt;span style="color:#e6db74">s&amp;#34;Failed to start JobMaster for job &lt;/span>&lt;span style="color:#e6db74">${&lt;/span>jobGraph&lt;span style="color:#f92672">.&lt;/span>getJobID&lt;span style="color:#e6db74">}&lt;/span>&lt;span style="color:#e6db74">&amp;#34;&lt;/span>&lt;span style="color:#f92672">,&lt;/span> e&lt;span style="color:#f92672">)&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">throw&lt;/span> e
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">}&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">}&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e">// 向ResourceManager注册JobMaster
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span> &lt;span style="color:#66d9ef">private&lt;/span> &lt;span style="color:#66d9ef">def&lt;/span> registerJobMasterWithResourceManager&lt;span style="color:#f92672">()&lt;/span>&lt;span style="color:#66d9ef">:&lt;/span> &lt;span style="color:#66d9ef">Unit&lt;/span> &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#f92672">{&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">val&lt;/span> registrationFuture &lt;span style="color:#66d9ef">=&lt;/span> resourceManagerGateway&lt;span style="color:#f92672">.&lt;/span>registerJobManager&lt;span style="color:#f92672">(&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> jobMasterGateway&lt;span style="color:#f92672">,&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> jobGraph&lt;span style="color:#f92672">.&lt;/span>getJobID&lt;span style="color:#f92672">,&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> jobMaster&lt;span style="color:#f92672">.&lt;/span>getAddress&lt;span style="color:#f92672">,&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> jobGraph&lt;span style="color:#f92672">.&lt;/span>getJobConfiguration&lt;span style="color:#f92672">)&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> registrationFuture&lt;span style="color:#f92672">.&lt;/span>whenComplete &lt;span style="color:#f92672">{&lt;/span> &lt;span style="color:#f92672">(&lt;/span>result&lt;span style="color:#f92672">,&lt;/span> throwable&lt;span style="color:#f92672">)&lt;/span> &lt;span style="color:#66d9ef">=&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">if&lt;/span> &lt;span style="color:#f92672">(&lt;/span>throwable &lt;span style="color:#f92672">!=&lt;/span> &lt;span style="color:#66d9ef">null&lt;/span>&lt;span style="color:#f92672">)&lt;/span> &lt;span style="color:#f92672">{&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> logError&lt;span style="color:#f92672">(&lt;/span>&lt;span style="color:#e6db74">&amp;#34;Failed to register JobMaster with ResourceManager&amp;#34;&lt;/span>&lt;span style="color:#f92672">,&lt;/span> throwable&lt;span style="color:#f92672">)&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> jobMaster&lt;span style="color:#f92672">.&lt;/span>failJob&lt;span style="color:#f92672">(&lt;/span>throwable&lt;span style="color:#f92672">)&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">}&lt;/span> &lt;span style="color:#66d9ef">else&lt;/span> &lt;span style="color:#f92672">{&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> logInfo&lt;span style="color:#f92672">(&lt;/span>&lt;span style="color:#e6db74">&amp;#34;Successfully registered JobMaster with ResourceManager&amp;#34;&lt;/span>&lt;span style="color:#f92672">)&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">}&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">}&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">}&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f92672">}&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h3 id="13-taskmanager启动流程">1.3 TaskManager启动流程&lt;/h3>
&lt;h4 id="taskmanager启动流程图">TaskManager启动流程图&lt;/h4>
&lt;div class="mermaid">graph TD
A[TaskManager进程启动] --> B[解析配置参数]
B --> C[创建TaskManagerServices]
C --> D[初始化内存管理器]
D --> E[创建网络环境]
E --> F[初始化Slot管理器]
F --> G[启动心跳服务]
G --> H[连接到ResourceManager]
H --> I[注册TaskManager]
I --> J[等待任务分配]
J --> K[接收任务部署请求]
K --> L[创建Task实例]
L --> M[启动Task执行]
M --> N[报告任务状态]
style A fill:#e1f5fe
style E fill:#fff3e0
style I fill:#e8f5e8
style N fill:#c8e6c9
&lt;/div>
&lt;h4 id="taskmanager启动核心源码">TaskManager启动核心源码&lt;/h4>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-scala" data-lang="scala">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">// TaskManagerRunner.scala - TaskManager启动核心类
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>&lt;span style="color:#66d9ef">class&lt;/span> &lt;span style="color:#a6e22e">TaskManagerRunner&lt;/span>&lt;span style="color:#f92672">(&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> configuration&lt;span style="color:#66d9ef">:&lt;/span> &lt;span style="color:#66d9ef">Configuration&lt;/span>&lt;span style="color:#f92672">,&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> resourceID&lt;span style="color:#66d9ef">:&lt;/span> &lt;span style="color:#66d9ef">ResourceID&lt;/span>&lt;span style="color:#f92672">)&lt;/span> &lt;span style="color:#f92672">{&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">private&lt;/span> &lt;span style="color:#66d9ef">var&lt;/span> taskManager&lt;span style="color:#66d9ef">:&lt;/span> &lt;span style="color:#66d9ef">TaskExecutor&lt;/span> &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#66d9ef">_&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">private&lt;/span> &lt;span style="color:#66d9ef">var&lt;/span> taskManagerService&lt;span style="color:#66d9ef">:&lt;/span> &lt;span style="color:#66d9ef">TaskManagerServices&lt;/span> &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#66d9ef">_&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e">// TaskManager启动的主要方法
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span> &lt;span style="color:#66d9ef">def&lt;/span> start&lt;span style="color:#f92672">()&lt;/span>&lt;span style="color:#66d9ef">:&lt;/span> &lt;span style="color:#66d9ef">CompletableFuture&lt;/span>&lt;span style="color:#f92672">[&lt;/span>&lt;span style="color:#66d9ef">Void&lt;/span>&lt;span style="color:#f92672">]&lt;/span> &lt;span style="color:#66d9ef">=&lt;/span> &lt;span style="color:#f92672">{&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">return&lt;/span> &lt;span style="color:#a6e22e">CompletableFuture&lt;/span>&lt;span style="color:#f92672">.&lt;/span>runAsync&lt;span style="color:#f92672">(()&lt;/span> &lt;span style="color:#66d9ef">=&amp;gt;&lt;/span> &lt;span style="color:#f92672">{&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">try&lt;/span> &lt;span style="color:#f92672">{&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e">// 1. 创建TaskManager服务组件
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span> taskManagerService &lt;span style="color:#66d9ef">=&lt;/span> &lt;span style="color:#a6e22e">TaskManagerServices&lt;/span>&lt;span style="color:#f92672">.&lt;/span>fromConfiguration&lt;span style="color:#f92672">(&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> configuration&lt;span style="color:#f92672">,&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> resourceID&lt;span style="color:#f92672">,&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> rpcService&lt;span style="color:#f92672">,&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> highAvailabilityServices&lt;span style="color:#f92672">,&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> heartbeatServices&lt;span style="color:#f92672">,&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> metricRegistry&lt;span style="color:#f92672">,&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> blobCacheService&lt;span style="color:#f92672">,&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> localRecoveryDirectoryProvider&lt;span style="color:#f92672">,&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> fatalErrorHandler&lt;span style="color:#f92672">)&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e">// 2. 创建TaskExecutor
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span> taskManager &lt;span style="color:#66d9ef">=&lt;/span> &lt;span style="color:#66d9ef">new&lt;/span> &lt;span style="color:#a6e22e">TaskExecutor&lt;/span>&lt;span style="color:#f92672">(&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> rpcService&lt;span style="color:#f92672">,&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> taskManagerService&lt;span style="color:#f92672">.&lt;/span>getTaskManagerConfiguration&lt;span style="color:#f92672">,&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> taskManagerService&lt;span style="color:#f92672">.&lt;/span>getTaskSlotTable&lt;span style="color:#f92672">,&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> taskManagerService&lt;span style="color:#f92672">.&lt;/span>getJobManagerTable&lt;span style="color:#f92672">,&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> taskManagerService&lt;span style="color:#f92672">.&lt;/span>getJobLeaderService&lt;span style="color:#f92672">,&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> taskManagerService&lt;span style="color:#f92672">.&lt;/span>getTaskStateManager&lt;span style="color:#f92672">,&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> taskManagerService&lt;span style="color:#f92672">.&lt;/span>getMemoryManager&lt;span style="color:#f92672">,&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> taskManagerService&lt;span style="color:#f92672">.&lt;/span>getIOManager&lt;span style="color:#f92672">,&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> taskManagerService&lt;span style="color:#f92672">.&lt;/span>getNetworkEnvironment&lt;span style="color:#f92672">,&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> taskManagerService&lt;span style="color:#f92672">.&lt;/span>getBroadcastVariableManager&lt;span style="color:#f92672">,&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> taskManagerService&lt;span style="color:#f92672">.&lt;/span>getTaskEventDispatcher&lt;span style="color:#f92672">,&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> taskManagerService&lt;span style="color:#f92672">.&lt;/span>getKvStateService&lt;span style="color:#f92672">,&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> fatalErrorHandler&lt;span style="color:#f92672">,&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> taskManagerService&lt;span style="color:#f92672">.&lt;/span>getPartitionTracker&lt;span style="color:#f92672">)&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e">// 3. 启动TaskExecutor
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span> taskManager&lt;span style="color:#f92672">.&lt;/span>start&lt;span style="color:#f92672">()&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e">// 4. 等待终止信号
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span> taskManager&lt;span style="color:#f92672">.&lt;/span>getTerminationFuture&lt;span style="color:#f92672">().&lt;/span>get&lt;span style="color:#f92672">()&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">}&lt;/span> &lt;span style="color:#66d9ef">catch&lt;/span> &lt;span style="color:#f92672">{&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">case&lt;/span> e&lt;span style="color:#66d9ef">:&lt;/span> &lt;span style="color:#66d9ef">Exception&lt;/span> &lt;span style="color:#f92672">=&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> logError&lt;span style="color:#f92672">(&lt;/span>&lt;span style="color:#e6db74">&amp;#34;Failed to start TaskManager&amp;#34;&lt;/span>&lt;span style="color:#f92672">,&lt;/span> e&lt;span style="color:#f92672">)&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">throw&lt;/span> &lt;span style="color:#66d9ef">new&lt;/span> &lt;span style="color:#a6e22e">RuntimeException&lt;/span>&lt;span style="color:#f92672">(&lt;/span>&lt;span style="color:#e6db74">&amp;#34;Failed to start TaskManager&amp;#34;&lt;/span>&lt;span style="color:#f92672">,&lt;/span> e&lt;span style="color:#f92672">)&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">}&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">},&lt;/span> ioExecutor&lt;span style="color:#f92672">)&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">}&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e">// TaskExecutor初始化和资源连接
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span> &lt;span style="color:#66d9ef">def&lt;/span> connectToResourceManager&lt;span style="color:#f92672">()&lt;/span>&lt;span style="color:#66d9ef">:&lt;/span> &lt;span style="color:#66d9ef">Unit&lt;/span> &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#f92672">{&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">val&lt;/span> resourceManagerAddress &lt;span style="color:#66d9ef">=&lt;/span> configuration&lt;span style="color:#f92672">.&lt;/span>getString&lt;span style="color:#f92672">(&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">JobManagerOptions&lt;/span>&lt;span style="color:#f92672">.&lt;/span>&lt;span style="color:#a6e22e">ADDRESS&lt;/span>&lt;span style="color:#f92672">)&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">val&lt;/span> resourceManagerPort &lt;span style="color:#66d9ef">=&lt;/span> configuration&lt;span style="color:#f92672">.&lt;/span>getInteger&lt;span style="color:#f92672">(&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">JobManagerOptions&lt;/span>&lt;span style="color:#f92672">.&lt;/span>&lt;span style="color:#a6e22e">PORT&lt;/span>&lt;span style="color:#f92672">)&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e">// 连接到ResourceManager
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span> &lt;span style="color:#66d9ef">val&lt;/span> connectionFuture &lt;span style="color:#66d9ef">=&lt;/span> taskManager&lt;span style="color:#f92672">.&lt;/span>connectToResourceManager&lt;span style="color:#f92672">(&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> resourceManagerAddress&lt;span style="color:#f92672">,&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> resourceManagerPort&lt;span style="color:#f92672">)&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> connectionFuture&lt;span style="color:#f92672">.&lt;/span>whenComplete &lt;span style="color:#f92672">{&lt;/span> &lt;span style="color:#f92672">(&lt;/span>connection&lt;span style="color:#f92672">,&lt;/span> throwable&lt;span style="color:#f92672">)&lt;/span> &lt;span style="color:#66d9ef">=&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">if&lt;/span> &lt;span style="color:#f92672">(&lt;/span>throwable &lt;span style="color:#f92672">!=&lt;/span> &lt;span style="color:#66d9ef">null&lt;/span>&lt;span style="color:#f92672">)&lt;/span> &lt;span style="color:#f92672">{&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> logError&lt;span style="color:#f92672">(&lt;/span>&lt;span style="color:#e6db74">&amp;#34;Failed to connect to ResourceManager&amp;#34;&lt;/span>&lt;span style="color:#f92672">,&lt;/span> throwable&lt;span style="color:#f92672">)&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> fatalErrorHandler&lt;span style="color:#f92672">.&lt;/span>onFatalError&lt;span style="color:#f92672">(&lt;/span>throwable&lt;span style="color:#f92672">)&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">}&lt;/span> &lt;span style="color:#66d9ef">else&lt;/span> &lt;span style="color:#f92672">{&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> logInfo&lt;span style="color:#f92672">(&lt;/span>&lt;span style="color:#e6db74">&amp;#34;Successfully connected to ResourceManager&amp;#34;&lt;/span>&lt;span style="color:#f92672">)&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">}&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">}&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">}&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f92672">}&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;hr>
&lt;h2 id="二作业图构建与优化-1">二、作业图构建与优化&lt;/h2>
&lt;h3 id="21-streamgraph构建">2.1 StreamGraph构建&lt;/h3>
&lt;h4 id="streamgraph构建流程图">StreamGraph构建流程图&lt;/h4>
&lt;div class="mermaid">graph TD
A[用户程序启动] --> B[调用StreamExecutionEnvironment]
B --> C[添加Source算子]
C --> D[添加Transformation算子]
D --> E[添加Sink算子]
E --> F["调用execute()方法"]
F --> G["StreamGraphGenerator.generate()"]
G --> H[遍历Transformations]
H --> I[创建StreamNode]
I --> J[创建StreamEdge]
J --> K[设置并行度和资源]
K --> L[配置链接策略]
L --> M[生成StreamGraph]
style A fill:#e1f5fe
style F fill:#fff3e0
style M fill:#e8f5e8
&lt;/div>
&lt;h4 id="streamgraph构建源码分析">StreamGraph构建源码分析&lt;/h4>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-scala" data-lang="scala">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">// StreamGraphGenerator.scala - StreamGraph生成器
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>&lt;span style="color:#66d9ef">class&lt;/span> &lt;span style="color:#a6e22e">StreamGraphGenerator&lt;/span>&lt;span style="color:#f92672">(&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> transformations&lt;span style="color:#66d9ef">:&lt;/span> &lt;span style="color:#66d9ef">util.List&lt;/span>&lt;span style="color:#f92672">[&lt;/span>&lt;span style="color:#66d9ef">Transformation&lt;/span>&lt;span style="color:#f92672">[&lt;/span>&lt;span style="color:#66d9ef">_&lt;/span>&lt;span style="color:#f92672">]],&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> config&lt;span style="color:#66d9ef">:&lt;/span> &lt;span style="color:#66d9ef">StreamExecutionEnvironment.Config&lt;/span>&lt;span style="color:#f92672">,&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> checkpointCfg&lt;span style="color:#66d9ef">:&lt;/span> &lt;span style="color:#66d9ef">CheckpointConfig&lt;/span>&lt;span style="color:#f92672">)&lt;/span> &lt;span style="color:#f92672">{&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">private&lt;/span> &lt;span style="color:#66d9ef">val&lt;/span> streamGraph &lt;span style="color:#66d9ef">=&lt;/span> &lt;span style="color:#66d9ef">new&lt;/span> &lt;span style="color:#a6e22e">StreamGraph&lt;/span>&lt;span style="color:#f92672">(&lt;/span>config&lt;span style="color:#f92672">.&lt;/span>getExecutionConfig&lt;span style="color:#f92672">,&lt;/span> checkpointCfg&lt;span style="color:#f92672">)&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">private&lt;/span> &lt;span style="color:#66d9ef">val&lt;/span> alreadyTransformed &lt;span style="color:#66d9ef">=&lt;/span> &lt;span style="color:#66d9ef">new&lt;/span> util&lt;span style="color:#f92672">.&lt;/span>&lt;span style="color:#a6e22e">HashMap&lt;/span>&lt;span style="color:#f92672">[&lt;/span>&lt;span style="color:#66d9ef">Transformation&lt;/span>&lt;span style="color:#f92672">[&lt;/span>&lt;span style="color:#66d9ef">_&lt;/span>&lt;span style="color:#f92672">]&lt;/span>, &lt;span style="color:#66d9ef">util.Collection&lt;/span>&lt;span style="color:#f92672">[&lt;/span>&lt;span style="color:#66d9ef">Integer&lt;/span>&lt;span style="color:#f92672">]]()&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e">// 生成StreamGraph的主要方法
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span> &lt;span style="color:#66d9ef">def&lt;/span> generate&lt;span style="color:#f92672">()&lt;/span>&lt;span style="color:#66d9ef">:&lt;/span> &lt;span style="color:#66d9ef">StreamGraph&lt;/span> &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#f92672">{&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e">// 1. 遍历所有的Transformation
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span> &lt;span style="color:#66d9ef">for&lt;/span> &lt;span style="color:#f92672">(&lt;/span>transformation &lt;span style="color:#66d9ef">&amp;lt;-&lt;/span> transformations&lt;span style="color:#f92672">.&lt;/span>asScala&lt;span style="color:#f92672">)&lt;/span> &lt;span style="color:#f92672">{&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> transform&lt;span style="color:#f92672">(&lt;/span>transformation&lt;span style="color:#f92672">)&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">}&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e">// 2. 设置环境配置
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span> streamGraph&lt;span style="color:#f92672">.&lt;/span>setEnvironmentConfig&lt;span style="color:#f92672">(&lt;/span>config&lt;span style="color:#f92672">)&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> streamGraph&lt;span style="color:#f92672">.&lt;/span>setCheckpointConfig&lt;span style="color:#f92672">(&lt;/span>checkpointCfg&lt;span style="color:#f92672">)&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> streamGraph&lt;span style="color:#f92672">.&lt;/span>setScheduleMode&lt;span style="color:#f92672">(&lt;/span>config&lt;span style="color:#f92672">.&lt;/span>getExecutionConfig&lt;span style="color:#f92672">.&lt;/span>getExecutionMode&lt;span style="color:#f92672">)&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e">// 3. 配置算子链接
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span> streamGraph&lt;span style="color:#f92672">.&lt;/span>setChaining&lt;span style="color:#f92672">(&lt;/span>config&lt;span style="color:#f92672">.&lt;/span>getExecutionConfig&lt;span style="color:#f92672">.&lt;/span>isChainingEnabled&lt;span style="color:#f92672">)&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e">// 4. 设置状态后端
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span> &lt;span style="color:#66d9ef">if&lt;/span> &lt;span style="color:#f92672">(&lt;/span>config&lt;span style="color:#f92672">.&lt;/span>getStateBackend &lt;span style="color:#f92672">!=&lt;/span> &lt;span style="color:#66d9ef">null&lt;/span>&lt;span style="color:#f92672">)&lt;/span> &lt;span style="color:#f92672">{&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> streamGraph&lt;span style="color:#f92672">.&lt;/span>setStateBackend&lt;span style="color:#f92672">(&lt;/span>config&lt;span style="color:#f92672">.&lt;/span>getStateBackend&lt;span style="color:#f92672">)&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">}&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> streamGraph
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">}&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e">// 转换单个Transformation为StreamNode
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span> &lt;span style="color:#66d9ef">private&lt;/span> &lt;span style="color:#66d9ef">def&lt;/span> transform&lt;span style="color:#f92672">(&lt;/span>transform&lt;span style="color:#66d9ef">:&lt;/span> &lt;span style="color:#66d9ef">Transformation&lt;/span>&lt;span style="color:#f92672">[&lt;/span>&lt;span style="color:#66d9ef">_&lt;/span>&lt;span style="color:#f92672">])&lt;/span>&lt;span style="color:#66d9ef">:&lt;/span> &lt;span style="color:#66d9ef">util.Collection&lt;/span>&lt;span style="color:#f92672">[&lt;/span>&lt;span style="color:#66d9ef">Integer&lt;/span>&lt;span style="color:#f92672">]&lt;/span> &lt;span style="color:#66d9ef">=&lt;/span> &lt;span style="color:#f92672">{&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">if&lt;/span> &lt;span style="color:#f92672">(&lt;/span>alreadyTransformed&lt;span style="color:#f92672">.&lt;/span>containsKey&lt;span style="color:#f92672">(&lt;/span>transform&lt;span style="color:#f92672">))&lt;/span> &lt;span style="color:#f92672">{&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">return&lt;/span> alreadyTransformed&lt;span style="color:#f92672">.&lt;/span>get&lt;span style="color:#f92672">(&lt;/span>transform&lt;span style="color:#f92672">)&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">}&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">val&lt;/span> transformationName &lt;span style="color:#66d9ef">=&lt;/span> transform&lt;span style="color:#f92672">.&lt;/span>getName
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">val&lt;/span> transformationUID &lt;span style="color:#66d9ef">=&lt;/span> transform&lt;span style="color:#f92672">.&lt;/span>getUid
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> transform &lt;span style="color:#66d9ef">match&lt;/span> &lt;span style="color:#f92672">{&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">case&lt;/span> sourceTransform&lt;span style="color:#66d9ef">:&lt;/span> &lt;span style="color:#66d9ef">SourceTransformation&lt;/span>&lt;span style="color:#f92672">[&lt;/span>&lt;span style="color:#66d9ef">_&lt;/span>&lt;span style="color:#f92672">]&lt;/span> &lt;span style="color:#66d9ef">=&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> transformSource&lt;span style="color:#f92672">(&lt;/span>sourceTransform&lt;span style="color:#f92672">)&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">case&lt;/span> sinkTransform&lt;span style="color:#66d9ef">:&lt;/span> &lt;span style="color:#66d9ef">SinkTransformation&lt;/span>&lt;span style="color:#f92672">[&lt;/span>&lt;span style="color:#66d9ef">_&lt;/span>&lt;span style="color:#f92672">]&lt;/span> &lt;span style="color:#66d9ef">=&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> transformSink&lt;span style="color:#f92672">(&lt;/span>sinkTransform&lt;span style="color:#f92672">)&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">case&lt;/span> oneInputTransform&lt;span style="color:#66d9ef">:&lt;/span> &lt;span style="color:#66d9ef">OneInputTransformation&lt;/span>&lt;span style="color:#f92672">[&lt;/span>&lt;span style="color:#66d9ef">_&lt;/span>, &lt;span style="color:#66d9ef">_&lt;/span>&lt;span style="color:#f92672">]&lt;/span> &lt;span style="color:#66d9ef">=&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> transformOneInput&lt;span style="color:#f92672">(&lt;/span>oneInputTransform&lt;span style="color:#f92672">)&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">case&lt;/span> twoInputTransform&lt;span style="color:#66d9ef">:&lt;/span> &lt;span style="color:#66d9ef">TwoInputTransformation&lt;/span>&lt;span style="color:#f92672">[&lt;/span>&lt;span style="color:#66d9ef">_&lt;/span>, &lt;span style="color:#66d9ef">_&lt;/span>, &lt;span style="color:#66d9ef">_&lt;/span>&lt;span style="color:#f92672">]&lt;/span> &lt;span style="color:#66d9ef">=&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> transformTwoInput&lt;span style="color:#f92672">(&lt;/span>twoInputTransform&lt;span style="color:#f92672">)&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">case&lt;/span> multiInputTransform&lt;span style="color:#66d9ef">:&lt;/span> &lt;span style="color:#66d9ef">MultiInputTransformation&lt;/span>&lt;span style="color:#f92672">[&lt;/span>&lt;span style="color:#66d9ef">_&lt;/span>&lt;span style="color:#f92672">]&lt;/span> &lt;span style="color:#66d9ef">=&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> transformMultiInput&lt;span style="color:#f92672">(&lt;/span>multiInputTransform&lt;span style="color:#f92672">)&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">case&lt;/span> &lt;span style="color:#66d9ef">_&lt;/span> &lt;span style="color:#66d9ef">=&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">throw&lt;/span> &lt;span style="color:#66d9ef">new&lt;/span> &lt;span style="color:#a6e22e">IllegalStateException&lt;/span>&lt;span style="color:#f92672">(&lt;/span>&lt;span style="color:#e6db74">s&amp;#34;Unknown transformation type: &lt;/span>&lt;span style="color:#e6db74">${&lt;/span>transform&lt;span style="color:#f92672">.&lt;/span>getClass&lt;span style="color:#e6db74">}&lt;/span>&lt;span style="color:#e6db74">&amp;#34;&lt;/span>&lt;span style="color:#f92672">)&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">}&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">}&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e">// 转换Source算子
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span> &lt;span style="color:#66d9ef">private&lt;/span> &lt;span style="color:#66d9ef">def&lt;/span> transformSource&lt;span style="color:#f92672">[&lt;/span>&lt;span style="color:#66d9ef">T&lt;/span>&lt;span style="color:#f92672">](&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> sourceTransform&lt;span style="color:#66d9ef">:&lt;/span> &lt;span style="color:#66d9ef">SourceTransformation&lt;/span>&lt;span style="color:#f92672">[&lt;/span>&lt;span style="color:#66d9ef">T&lt;/span>&lt;span style="color:#f92672">])&lt;/span>&lt;span style="color:#66d9ef">:&lt;/span> &lt;span style="color:#66d9ef">util.Collection&lt;/span>&lt;span style="color:#f92672">[&lt;/span>&lt;span style="color:#66d9ef">Integer&lt;/span>&lt;span style="color:#f92672">]&lt;/span> &lt;span style="color:#66d9ef">=&lt;/span> &lt;span style="color:#f92672">{&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e">// 1. 创建StreamNode
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span> &lt;span style="color:#66d9ef">val&lt;/span> nodeId &lt;span style="color:#66d9ef">=&lt;/span> streamGraph&lt;span style="color:#f92672">.&lt;/span>addSource&lt;span style="color:#f92672">(&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> sourceTransform&lt;span style="color:#f92672">.&lt;/span>getOperatorFactory&lt;span style="color:#f92672">,&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> sourceTransform&lt;span style="color:#f92672">.&lt;/span>getInputType&lt;span style="color:#f92672">,&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> sourceTransform&lt;span style="color:#f92672">.&lt;/span>getOutputType&lt;span style="color:#f92672">,&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> sourceTransform&lt;span style="color:#f92672">.&lt;/span>getName&lt;span style="color:#f92672">)&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e">// 2. 设置并行度
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span> &lt;span style="color:#66d9ef">if&lt;/span> &lt;span style="color:#f92672">(&lt;/span>sourceTransform&lt;span style="color:#f92672">.&lt;/span>getParallelism &lt;span style="color:#f92672">!=&lt;/span> &lt;span style="color:#f92672">-&lt;/span>&lt;span style="color:#ae81ff">1&lt;/span>&lt;span style="color:#f92672">)&lt;/span> &lt;span style="color:#f92672">{&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> streamGraph&lt;span style="color:#f92672">.&lt;/span>setParallelism&lt;span style="color:#f92672">(&lt;/span>nodeId&lt;span style="color:#f92672">,&lt;/span> sourceTransform&lt;span style="color:#f92672">.&lt;/span>getParallelism&lt;span style="color:#f92672">)&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">}&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e">// 3. 设置资源需求
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span> &lt;span style="color:#66d9ef">if&lt;/span> &lt;span style="color:#f92672">(&lt;/span>sourceTransform&lt;span style="color:#f92672">.&lt;/span>getMinResources &lt;span style="color:#f92672">!=&lt;/span> &lt;span style="color:#66d9ef">null&lt;/span>&lt;span style="color:#f92672">)&lt;/span> &lt;span style="color:#f92672">{&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> streamGraph&lt;span style="color:#f92672">.&lt;/span>setResources&lt;span style="color:#f92672">(&lt;/span>nodeId&lt;span style="color:#f92672">,&lt;/span> sourceTransform&lt;span style="color:#f92672">.&lt;/span>getMinResources&lt;span style="color:#f92672">,&lt;/span> sourceTransform&lt;span style="color:#f92672">.&lt;/span>getPreferredResources&lt;span style="color:#f92672">)&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">}&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e">// 4. 设置Slot共享组
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span> streamGraph&lt;span style="color:#f92672">.&lt;/span>setSlotSharingGroup&lt;span style="color:#f92672">(&lt;/span>nodeId&lt;span style="color:#f92672">,&lt;/span> sourceTransform&lt;span style="color:#f92672">.&lt;/span>getSlotSharingGroup&lt;span style="color:#f92672">)&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">val&lt;/span> result &lt;span style="color:#66d9ef">=&lt;/span> util&lt;span style="color:#f92672">.&lt;/span>&lt;span style="color:#a6e22e">Collections&lt;/span>&lt;span style="color:#f92672">.&lt;/span>singletonList&lt;span style="color:#f92672">(&lt;/span>nodeId&lt;span style="color:#f92672">)&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> alreadyTransformed&lt;span style="color:#f92672">.&lt;/span>put&lt;span style="color:#f92672">(&lt;/span>sourceTransform&lt;span style="color:#f92672">,&lt;/span> result&lt;span style="color:#f92672">)&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> result
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">}&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e">// 转换单输入算子
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span> &lt;span style="color:#66d9ef">private&lt;/span> &lt;span style="color:#66d9ef">def&lt;/span> transformOneInput&lt;span style="color:#f92672">[&lt;/span>&lt;span style="color:#66d9ef">IN&lt;/span>, &lt;span style="color:#66d9ef">OUT&lt;/span>&lt;span style="color:#f92672">](&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> transform&lt;span style="color:#66d9ef">:&lt;/span> &lt;span style="color:#66d9ef">OneInputTransformation&lt;/span>&lt;span style="color:#f92672">[&lt;/span>&lt;span style="color:#66d9ef">IN&lt;/span>, &lt;span style="color:#66d9ef">OUT&lt;/span>&lt;span style="color:#f92672">])&lt;/span>&lt;span style="color:#66d9ef">:&lt;/span> &lt;span style="color:#66d9ef">util.Collection&lt;/span>&lt;span style="color:#f92672">[&lt;/span>&lt;span style="color:#66d9ef">Integer&lt;/span>&lt;span style="color:#f92672">]&lt;/span> &lt;span style="color:#66d9ef">=&lt;/span> &lt;span style="color:#f92672">{&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e">// 1. 递归处理输入Transformation
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span> &lt;span style="color:#66d9ef">val&lt;/span> inputIds &lt;span style="color:#66d9ef">=&lt;/span> transform&lt;span style="color:#f92672">(&lt;/span>transform&lt;span style="color:#f92672">.&lt;/span>getInput&lt;span style="color:#f92672">)&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e">// 2. 创建StreamNode
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span> &lt;span style="color:#66d9ef">val&lt;/span> nodeId &lt;span style="color:#66d9ef">=&lt;/span> streamGraph&lt;span style="color:#f92672">.&lt;/span>addOperator&lt;span style="color:#f92672">(&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> transform&lt;span style="color:#f92672">.&lt;/span>getOperatorFactory&lt;span style="color:#f92672">,&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> transform&lt;span style="color:#f92672">.&lt;/span>getInputType&lt;span style="color:#f92672">,&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> transform&lt;span style="color:#f92672">.&lt;/span>getOutputType&lt;span style="color:#f92672">,&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> transform&lt;span style="color:#f92672">.&lt;/span>getName&lt;span style="color:#f92672">)&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e">// 3. 创建StreamEdge连接输入和当前节点
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span> &lt;span style="color:#66d9ef">for&lt;/span> &lt;span style="color:#f92672">(&lt;/span>inputId &lt;span style="color:#66d9ef">&amp;lt;-&lt;/span> inputIds&lt;span style="color:#f92672">.&lt;/span>asScala&lt;span style="color:#f92672">)&lt;/span> &lt;span style="color:#f92672">{&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> streamGraph&lt;span style="color:#f92672">.&lt;/span>addEdge&lt;span style="color:#f92672">(&lt;/span>inputId&lt;span style="color:#f92672">,&lt;/span> nodeId&lt;span style="color:#f92672">,&lt;/span> &lt;span style="color:#ae81ff">0&lt;/span>&lt;span style="color:#f92672">)&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">}&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e">// 4. 配置节点属性
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span> configureNode&lt;span style="color:#f92672">(&lt;/span>nodeId&lt;span style="color:#f92672">,&lt;/span> transform&lt;span style="color:#f92672">)&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">val&lt;/span> result &lt;span style="color:#66d9ef">=&lt;/span> util&lt;span style="color:#f92672">.&lt;/span>&lt;span style="color:#a6e22e">Collections&lt;/span>&lt;span style="color:#f92672">.&lt;/span>singletonList&lt;span style="color:#f92672">(&lt;/span>nodeId&lt;span style="color:#f92672">)&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> alreadyTransformed&lt;span style="color:#f92672">.&lt;/span>put&lt;span style="color:#f92672">(&lt;/span>transform&lt;span style="color:#f92672">,&lt;/span> result&lt;span style="color:#f92672">)&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> result
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">}&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e">// 配置StreamNode的通用属性
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span> &lt;span style="color:#66d9ef">private&lt;/span> &lt;span style="color:#66d9ef">def&lt;/span> configureNode&lt;span style="color:#f92672">(&lt;/span>nodeId&lt;span style="color:#66d9ef">:&lt;/span> &lt;span style="color:#66d9ef">Integer&lt;/span>&lt;span style="color:#f92672">,&lt;/span> transform&lt;span style="color:#66d9ef">:&lt;/span> &lt;span style="color:#66d9ef">Transformation&lt;/span>&lt;span style="color:#f92672">[&lt;/span>&lt;span style="color:#66d9ef">_&lt;/span>&lt;span style="color:#f92672">])&lt;/span>&lt;span style="color:#66d9ef">:&lt;/span> &lt;span style="color:#66d9ef">Unit&lt;/span> &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#f92672">{&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e">// 设置并行度
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span> &lt;span style="color:#66d9ef">if&lt;/span> &lt;span style="color:#f92672">(&lt;/span>transform&lt;span style="color:#f92672">.&lt;/span>getParallelism &lt;span style="color:#f92672">!=&lt;/span> &lt;span style="color:#f92672">-&lt;/span>&lt;span style="color:#ae81ff">1&lt;/span>&lt;span style="color:#f92672">)&lt;/span> &lt;span style="color:#f92672">{&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> streamGraph&lt;span style="color:#f92672">.&lt;/span>setParallelism&lt;span style="color:#f92672">(&lt;/span>nodeId&lt;span style="color:#f92672">,&lt;/span> transform&lt;span style="color:#f92672">.&lt;/span>getParallelism&lt;span style="color:#f92672">)&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">}&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e">// 设置最大并行度
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span> &lt;span style="color:#66d9ef">if&lt;/span> &lt;span style="color:#f92672">(&lt;/span>transform&lt;span style="color:#f92672">.&lt;/span>getMaxParallelism &lt;span style="color:#f92672">&amp;gt;&lt;/span> &lt;span style="color:#ae81ff">0&lt;/span>&lt;span style="color:#f92672">)&lt;/span> &lt;span style="color:#f92672">{&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> streamGraph&lt;span style="color:#f92672">.&lt;/span>setMaxParallelism&lt;span style="color:#f92672">(&lt;/span>nodeId&lt;span style="color:#f92672">,&lt;/span> transform&lt;span style="color:#f92672">.&lt;/span>getMaxParallelism&lt;span style="color:#f92672">)&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">}&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e">// 设置资源需求
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span> &lt;span style="color:#66d9ef">if&lt;/span> &lt;span style="color:#f92672">(&lt;/span>transform&lt;span style="color:#f92672">.&lt;/span>getMinResources &lt;span style="color:#f92672">!=&lt;/span> &lt;span style="color:#66d9ef">null&lt;/span>&lt;span style="color:#f92672">)&lt;/span> &lt;span style="color:#f92672">{&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> streamGraph&lt;span style="color:#f92672">.&lt;/span>setResources&lt;span style="color:#f92672">(&lt;/span>nodeId&lt;span style="color:#f92672">,&lt;/span> transform&lt;span style="color:#f92672">.&lt;/span>getMinResources&lt;span style="color:#f92672">,&lt;/span> transform&lt;span style="color:#f92672">.&lt;/span>getPreferredResources&lt;span style="color:#f92672">)&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">}&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e">// 设置Slot共享组
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span> streamGraph&lt;span style="color:#f92672">.&lt;/span>setSlotSharingGroup&lt;span style="color:#f92672">(&lt;/span>nodeId&lt;span style="color:#f92672">,&lt;/span> transform&lt;span style="color:#f92672">.&lt;/span>getSlotSharingGroup&lt;span style="color:#f92672">)&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e">// 设置算子链接策略
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span> streamGraph&lt;span style="color:#f92672">.&lt;/span>setChainingStrategy&lt;span style="color:#f92672">(&lt;/span>nodeId&lt;span style="color:#f92672">,&lt;/span> transform&lt;span style="color:#f92672">.&lt;/span>getChainingStrategy&lt;span style="color:#f92672">)&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">}&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f92672">}&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h3 id="22-jobgraph生成">2.2 JobGraph生成&lt;/h3>
&lt;h4 id="jobgraph优化流程图">JobGraph优化流程图&lt;/h4>
&lt;div class="mermaid">graph TD
A[StreamGraph] --> B[算子链接分析]
B --> C[创建JobVertex]
C --> D[设置JobEdge]
D --> E[配置输入输出]
E --> F[资源需求计算]
F --> G[检查点配置]
G --> H[生成JobGraph]
B --> B1[识别可链接算子]
B1 --> B2[合并算子]
B2 --> B3[创建算子链]
B3 --> C
style A fill:#e1f5fe
style B1 fill:#fff3e0
style H fill:#e8f5e8
&lt;/div>
&lt;h4 id="jobgraph生成核心源码">JobGraph生成核心源码&lt;/h4>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-scala" data-lang="scala">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">// StreamingJobGraphGenerator.scala - JobGraph生成器
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>&lt;span style="color:#66d9ef">class&lt;/span> &lt;span style="color:#a6e22e">StreamingJobGraphGenerator&lt;/span>&lt;span style="color:#f92672">(&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> streamGraph&lt;span style="color:#66d9ef">:&lt;/span> &lt;span style="color:#66d9ef">StreamGraph&lt;/span>&lt;span style="color:#f92672">,&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> jobID&lt;span style="color:#66d9ef">:&lt;/span> &lt;span style="color:#66d9ef">JobID&lt;/span>&lt;span style="color:#f92672">)&lt;/span> &lt;span style="color:#f92672">{&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">private&lt;/span> &lt;span style="color:#66d9ef">val&lt;/span> jobGraph &lt;span style="color:#66d9ef">=&lt;/span> &lt;span style="color:#66d9ef">new&lt;/span> &lt;span style="color:#a6e22e">JobGraph&lt;/span>&lt;span style="color:#f92672">(&lt;/span>jobID&lt;span style="color:#f92672">,&lt;/span> streamGraph&lt;span style="color:#f92672">.&lt;/span>getJobName&lt;span style="color:#f92672">)&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">private&lt;/span> &lt;span style="color:#66d9ef">val&lt;/span> chainedConfigs &lt;span style="color:#66d9ef">=&lt;/span> &lt;span style="color:#66d9ef">new&lt;/span> util&lt;span style="color:#f92672">.&lt;/span>&lt;span style="color:#a6e22e">HashMap&lt;/span>&lt;span style="color:#f92672">[&lt;/span>&lt;span style="color:#66d9ef">Integer&lt;/span>, &lt;span style="color:#66d9ef">StreamConfig&lt;/span>&lt;span style="color:#f92672">]()&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">private&lt;/span> &lt;span style="color:#66d9ef">val&lt;/span> vertexConfigs &lt;span style="color:#66d9ef">=&lt;/span> &lt;span style="color:#66d9ef">new&lt;/span> util&lt;span style="color:#f92672">.&lt;/span>&lt;span style="color:#a6e22e">HashMap&lt;/span>&lt;span style="color:#f92672">[&lt;/span>&lt;span style="color:#66d9ef">Integer&lt;/span>, &lt;span style="color:#66d9ef">StreamConfig&lt;/span>&lt;span style="color:#f92672">]()&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e">// 生成JobGraph的主要入口
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span> &lt;span style="color:#66d9ef">def&lt;/span> createJobGraph&lt;span style="color:#f92672">()&lt;/span>&lt;span style="color:#66d9ef">:&lt;/span> &lt;span style="color:#66d9ef">JobGraph&lt;/span> &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#f92672">{&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> preValidate&lt;span style="color:#f92672">()&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e">// 1. 设置调度模式
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span> jobGraph&lt;span style="color:#f92672">.&lt;/span>setScheduleMode&lt;span style="color:#f92672">(&lt;/span>streamGraph&lt;span style="color:#f92672">.&lt;/span>getScheduleMode&lt;span style="color:#f92672">)&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> jobGraph&lt;span style="color:#f92672">.&lt;/span>enableApproximateLocalRecovery&lt;span style="color:#f92672">(&lt;/span>streamGraph&lt;span style="color:#f92672">.&lt;/span>getCheckpointConfig&lt;span style="color:#f92672">.&lt;/span>isApproximateLocalRecoveryEnabled&lt;span style="color:#f92672">)&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e">// 2. 设置检查点配置
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span> configureCheckpointing&lt;span style="color:#f92672">()&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e">// 3. 设置SavePoint配置
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span> jobGraph&lt;span style="color:#f92672">.&lt;/span>setSavepointRestoreSettings&lt;span style="color:#f92672">(&lt;/span>streamGraph&lt;span style="color:#f92672">.&lt;/span>getSavepointRestoreSettings&lt;span style="color:#f92672">)&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e">// 4. 创建算子链
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span> setChaining&lt;span style="color:#f92672">()&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e">// 5. 配置JobVertex
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span> &lt;span style="color:#66d9ef">for&lt;/span> &lt;span style="color:#f92672">((&lt;/span>vertexID&lt;span style="color:#f92672">,&lt;/span> vertex&lt;span style="color:#f92672">)&lt;/span> &lt;span style="color:#66d9ef">&amp;lt;-&lt;/span> jobVertices&lt;span style="color:#f92672">.&lt;/span>asScala&lt;span style="color:#f92672">)&lt;/span> &lt;span style="color:#f92672">{&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> configureJobVertex&lt;span style="color:#f92672">(&lt;/span>vertex&lt;span style="color:#f92672">)&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">}&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e">// 6. 设置Slot共享和Co-location约束
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span> setSlotSharingAndCoLocation&lt;span style="color:#f92672">()&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e">// 7. 配置检查点钩子
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span> configureCheckpointHooks&lt;span style="color:#f92672">()&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> jobGraph
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">}&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e">// 算子链接的核心逻辑
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span> &lt;span style="color:#66d9ef">private&lt;/span> &lt;span style="color:#66d9ef">def&lt;/span> setChaining&lt;span style="color:#f92672">()&lt;/span>&lt;span style="color:#66d9ef">:&lt;/span> &lt;span style="color:#66d9ef">Unit&lt;/span> &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#f92672">{&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e">// 1. 找到所有的Source节点
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span> &lt;span style="color:#66d9ef">val&lt;/span> sourceNodes &lt;span style="color:#66d9ef">=&lt;/span> streamGraph&lt;span style="color:#f92672">.&lt;/span>getSourceIDs&lt;span style="color:#f92672">.&lt;/span>asScala
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">for&lt;/span> &lt;span style="color:#f92672">(&lt;/span>sourceNodeId &lt;span style="color:#66d9ef">&amp;lt;-&lt;/span> sourceNodes&lt;span style="color:#f92672">)&lt;/span> &lt;span style="color:#f92672">{&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e">// 2. 从Source开始创建算子链
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span> createChain&lt;span style="color:#f92672">(&lt;/span>sourceNodeId&lt;span style="color:#f92672">,&lt;/span> sourceNodeId&lt;span style="color:#f92672">,&lt;/span> hashes&lt;span style="color:#f92672">,&lt;/span> legacyHashes&lt;span style="color:#f92672">,&lt;/span> &lt;span style="color:#ae81ff">0&lt;/span>&lt;span style="color:#f92672">,&lt;/span> chainIndex&lt;span style="color:#f92672">)&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">}&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">}&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e">// 创建算子链的递归方法
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span> &lt;span style="color:#66d9ef">private&lt;/span> &lt;span style="color:#66d9ef">def&lt;/span> createChain&lt;span style="color:#f92672">(&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> startNodeId&lt;span style="color:#66d9ef">:&lt;/span> &lt;span style="color:#66d9ef">Integer&lt;/span>&lt;span style="color:#f92672">,&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> currentNodeId&lt;span style="color:#66d9ef">:&lt;/span> &lt;span style="color:#66d9ef">Integer&lt;/span>&lt;span style="color:#f92672">,&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> hashes&lt;span style="color:#66d9ef">:&lt;/span> &lt;span style="color:#66d9ef">util.Map&lt;/span>&lt;span style="color:#f92672">[&lt;/span>&lt;span style="color:#66d9ef">Integer&lt;/span>, &lt;span style="color:#66d9ef">Array&lt;/span>&lt;span style="color:#f92672">[&lt;/span>&lt;span style="color:#66d9ef">Byte&lt;/span>&lt;span style="color:#f92672">]],&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> legacyHashes&lt;span style="color:#66d9ef">:&lt;/span> &lt;span style="color:#66d9ef">util.Map&lt;/span>&lt;span style="color:#f92672">[&lt;/span>&lt;span style="color:#66d9ef">Integer&lt;/span>, &lt;span style="color:#66d9ef">Array&lt;/span>&lt;span style="color:#f92672">[&lt;/span>&lt;span style="color:#66d9ef">Byte&lt;/span>&lt;span style="color:#f92672">]],&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> chainIndex&lt;span style="color:#66d9ef">:&lt;/span> &lt;span style="color:#66d9ef">Int&lt;/span>&lt;span style="color:#f92672">,&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> chainLength&lt;span style="color:#66d9ef">:&lt;/span> &lt;span style="color:#66d9ef">Int&lt;/span>&lt;span style="color:#f92672">)&lt;/span>&lt;span style="color:#66d9ef">:&lt;/span> &lt;span style="color:#66d9ef">util.List&lt;/span>&lt;span style="color:#f92672">[&lt;/span>&lt;span style="color:#66d9ef">StreamEdge&lt;/span>&lt;span style="color:#f92672">]&lt;/span> &lt;span style="color:#66d9ef">=&lt;/span> &lt;span style="color:#f92672">{&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">val&lt;/span> currentNode &lt;span style="color:#66d9ef">=&lt;/span> streamGraph&lt;span style="color:#f92672">.&lt;/span>getStreamNode&lt;span style="color:#f92672">(&lt;/span>currentNodeId&lt;span style="color:#f92672">)&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">val&lt;/span> chainableOutputs &lt;span style="color:#66d9ef">=&lt;/span> &lt;span style="color:#66d9ef">new&lt;/span> util&lt;span style="color:#f92672">.&lt;/span>&lt;span style="color:#a6e22e">ArrayList&lt;/span>&lt;span style="color:#f92672">[&lt;/span>&lt;span style="color:#66d9ef">StreamEdge&lt;/span>&lt;span style="color:#f92672">]()&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">val&lt;/span> nonChainableOutputs &lt;span style="color:#66d9ef">=&lt;/span> &lt;span style="color:#66d9ef">new&lt;/span> util&lt;span style="color:#f92672">.&lt;/span>&lt;span style="color:#a6e22e">ArrayList&lt;/span>&lt;span style="color:#f92672">[&lt;/span>&lt;span style="color:#66d9ef">StreamEdge&lt;/span>&lt;span style="color:#f92672">]()&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e">// 1. 分析输出边，判断是否可以链接
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span> &lt;span style="color:#66d9ef">for&lt;/span> &lt;span style="color:#f92672">(&lt;/span>outEdge &lt;span style="color:#66d9ef">&amp;lt;-&lt;/span> currentNode&lt;span style="color:#f92672">.&lt;/span>getOutEdges&lt;span style="color:#f92672">.&lt;/span>asScala&lt;span style="color:#f92672">)&lt;/span> &lt;span style="color:#f92672">{&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">if&lt;/span> &lt;span style="color:#f92672">(&lt;/span>isChainable&lt;span style="color:#f92672">(&lt;/span>outEdge&lt;span style="color:#f92672">,&lt;/span> streamGraph&lt;span style="color:#f92672">))&lt;/span> &lt;span style="color:#f92672">{&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> chainableOutputs&lt;span style="color:#f92672">.&lt;/span>add&lt;span style="color:#f92672">(&lt;/span>outEdge&lt;span style="color:#f92672">)&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">}&lt;/span> &lt;span style="color:#66d9ef">else&lt;/span> &lt;span style="color:#f92672">{&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> nonChainableOutputs&lt;span style="color:#f92672">.&lt;/span>add&lt;span style="color:#f92672">(&lt;/span>outEdge&lt;span style="color:#f92672">)&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">}&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">}&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e">// 2. 递归处理可链接的输出
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span> &lt;span style="color:#66d9ef">for&lt;/span> &lt;span style="color:#f92672">(&lt;/span>chainableOutput &lt;span style="color:#66d9ef">&amp;lt;-&lt;/span> chainableOutputs&lt;span style="color:#f92672">.&lt;/span>asScala&lt;span style="color:#f92672">)&lt;/span> &lt;span style="color:#f92672">{&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> createChain&lt;span style="color:#f92672">(&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> startNodeId&lt;span style="color:#f92672">,&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> chainableOutput&lt;span style="color:#f92672">.&lt;/span>getTargetId&lt;span style="color:#f92672">,&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> hashes&lt;span style="color:#f92672">,&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> legacyHashes&lt;span style="color:#f92672">,&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> chainIndex&lt;span style="color:#f92672">,&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> chainLength &lt;span style="color:#f92672">+&lt;/span> &lt;span style="color:#ae81ff">1&lt;/span>&lt;span style="color:#f92672">)&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">}&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e">// 3. 如果当前节点是链的起始节点，创建JobVertex
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span> &lt;span style="color:#66d9ef">if&lt;/span> &lt;span style="color:#f92672">(&lt;/span>currentNodeId &lt;span style="color:#f92672">==&lt;/span> startNodeId&lt;span style="color:#f92672">)&lt;/span> &lt;span style="color:#f92672">{&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">val&lt;/span> jobVertex &lt;span style="color:#66d9ef">=&lt;/span> createJobVertex&lt;span style="color:#f92672">(&lt;/span>startNodeId&lt;span style="color:#f92672">,&lt;/span> hashes&lt;span style="color:#f92672">,&lt;/span> legacyHashes&lt;span style="color:#f92672">,&lt;/span> chainedSources&lt;span style="color:#f92672">)&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e">// 4. 处理非链接输出
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span> &lt;span style="color:#66d9ef">for&lt;/span> &lt;span style="color:#f92672">(&lt;/span>nonChainableOutput &lt;span style="color:#66d9ef">&amp;lt;-&lt;/span> nonChainableOutputs&lt;span style="color:#f92672">.&lt;/span>asScala&lt;span style="color:#f92672">)&lt;/span> &lt;span style="color:#f92672">{&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">val&lt;/span> targetChainStartNode &lt;span style="color:#66d9ef">=&lt;/span> createChain&lt;span style="color:#f92672">(&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> nonChainableOutput&lt;span style="color:#f92672">.&lt;/span>getTargetId&lt;span style="color:#f92672">,&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> nonChainableOutput&lt;span style="color:#f92672">.&lt;/span>getTargetId&lt;span style="color:#f92672">,&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> hashes&lt;span style="color:#f92672">,&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> legacyHashes&lt;span style="color:#f92672">,&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> chainIndex &lt;span style="color:#f92672">+&lt;/span> &lt;span style="color:#ae81ff">1&lt;/span>&lt;span style="color:#f92672">,&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ae81ff">0&lt;/span>&lt;span style="color:#f92672">)&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e">// 创建JobEdge连接JobVertex
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span> &lt;span style="color:#66d9ef">val&lt;/span> jobEdge &lt;span style="color:#66d9ef">=&lt;/span> &lt;span style="color:#66d9ef">new&lt;/span> &lt;span style="color:#a6e22e">JobEdge&lt;/span>&lt;span style="color:#f92672">(&lt;/span>targetVertex&lt;span style="color:#f92672">,&lt;/span> &lt;span style="color:#a6e22e">DistributionPattern&lt;/span>&lt;span style="color:#f92672">.&lt;/span>&lt;span style="color:#a6e22e">POINTWISE&lt;/span>&lt;span style="color:#f92672">)&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> jobVertex&lt;span style="color:#f92672">.&lt;/span>connectNewDataSetAsInput&lt;span style="color:#f92672">(&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> targetVertex&lt;span style="color:#f92672">,&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">DistributionPattern&lt;/span>&lt;span style="color:#f92672">.&lt;/span>&lt;span style="color:#a6e22e">POINTWISE&lt;/span>&lt;span style="color:#f92672">,&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">ResultPartitionType&lt;/span>&lt;span style="color:#f92672">.&lt;/span>&lt;span style="color:#a6e22e">PIPELINED&lt;/span>&lt;span style="color:#f92672">)&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">}&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">}&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> chainableOutputs
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">}&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e">// 判断两个算子是否可以链接
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span> &lt;span style="color:#66d9ef">private&lt;/span> &lt;span style="color:#66d9ef">def&lt;/span> isChainable&lt;span style="color:#f92672">(&lt;/span>edge&lt;span style="color:#66d9ef">:&lt;/span> &lt;span style="color:#66d9ef">StreamEdge&lt;/span>&lt;span style="color:#f92672">,&lt;/span> streamGraph&lt;span style="color:#66d9ef">:&lt;/span> &lt;span style="color:#66d9ef">StreamGraph&lt;/span>&lt;span style="color:#f92672">)&lt;/span>&lt;span style="color:#66d9ef">:&lt;/span> &lt;span style="color:#66d9ef">Boolean&lt;/span> &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#f92672">{&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">val&lt;/span> downStreamVertex &lt;span style="color:#66d9ef">=&lt;/span> streamGraph&lt;span style="color:#f92672">.&lt;/span>getTargetVertex&lt;span style="color:#f92672">(&lt;/span>edge&lt;span style="color:#f92672">)&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">val&lt;/span> upStreamVertex &lt;span style="color:#66d9ef">=&lt;/span> streamGraph&lt;span style="color:#f92672">.&lt;/span>getSourceVertex&lt;span style="color:#f92672">(&lt;/span>edge&lt;span style="color:#f92672">)&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e">// 检查链接条件
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span> &lt;span style="color:#66d9ef">return&lt;/span> upStreamVertex&lt;span style="color:#f92672">.&lt;/span>isSameSlotSharingGroup&lt;span style="color:#f92672">(&lt;/span>downStreamVertex&lt;span style="color:#f92672">)&lt;/span> &lt;span style="color:#f92672">&amp;amp;&amp;amp;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> areOperatorsChainable&lt;span style="color:#f92672">(&lt;/span>upStreamVertex&lt;span style="color:#f92672">,&lt;/span> downStreamVertex&lt;span style="color:#f92672">,&lt;/span> streamGraph&lt;span style="color:#f92672">)&lt;/span> &lt;span style="color:#f92672">&amp;amp;&amp;amp;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">(&lt;/span>edge&lt;span style="color:#f92672">.&lt;/span>getPartitioner &lt;span style="color:#66d9ef">match&lt;/span> &lt;span style="color:#f92672">{&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">case&lt;/span> &lt;span style="color:#66d9ef">_:&lt;/span> &lt;span style="color:#66d9ef">ForwardPartitioner&lt;/span> &lt;span style="color:#f92672">=&amp;gt;&lt;/span> &lt;span style="color:#66d9ef">true&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">case&lt;/span> &lt;span style="color:#66d9ef">_:&lt;/span> &lt;span style="color:#66d9ef">RescalePartitioner&lt;/span> &lt;span style="color:#f92672">=&amp;gt;&lt;/span> upStreamVertex&lt;span style="color:#f92672">.&lt;/span>getParallelism &lt;span style="color:#f92672">==&lt;/span> downStreamVertex&lt;span style="color:#f92672">.&lt;/span>getParallelism
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">case&lt;/span> &lt;span style="color:#66d9ef">_&lt;/span> &lt;span style="color:#66d9ef">=&amp;gt;&lt;/span> &lt;span style="color:#66d9ef">false&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">})&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">}&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e">// 创建JobVertex
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span> &lt;span style="color:#66d9ef">private&lt;/span> &lt;span style="color:#66d9ef">def&lt;/span> createJobVertex&lt;span style="color:#f92672">(&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> streamNodeId&lt;span style="color:#66d9ef">:&lt;/span> &lt;span style="color:#66d9ef">Integer&lt;/span>&lt;span style="color:#f92672">,&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> hashes&lt;span style="color:#66d9ef">:&lt;/span> &lt;span style="color:#66d9ef">util.Map&lt;/span>&lt;span style="color:#f92672">[&lt;/span>&lt;span style="color:#66d9ef">Integer&lt;/span>, &lt;span style="color:#66d9ef">Array&lt;/span>&lt;span style="color:#f92672">[&lt;/span>&lt;span style="color:#66d9ef">Byte&lt;/span>&lt;span style="color:#f92672">]],&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> legacyHashes&lt;span style="color:#66d9ef">:&lt;/span> &lt;span style="color:#66d9ef">util.Map&lt;/span>&lt;span style="color:#f92672">[&lt;/span>&lt;span style="color:#66d9ef">Integer&lt;/span>, &lt;span style="color:#66d9ef">Array&lt;/span>&lt;span style="color:#f92672">[&lt;/span>&lt;span style="color:#66d9ef">Byte&lt;/span>&lt;span style="color:#f92672">]],&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> chainedSources&lt;span style="color:#66d9ef">:&lt;/span> &lt;span style="color:#66d9ef">util.List&lt;/span>&lt;span style="color:#f92672">[&lt;/span>&lt;span style="color:#66d9ef">Integer&lt;/span>&lt;span style="color:#f92672">])&lt;/span>&lt;span style="color:#66d9ef">:&lt;/span> &lt;span style="color:#66d9ef">JobVertex&lt;/span> &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#f92672">{&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">val&lt;/span> streamNode &lt;span style="color:#66d9ef">=&lt;/span> streamGraph&lt;span style="color:#f92672">.&lt;/span>getStreamNode&lt;span style="color:#f92672">(&lt;/span>streamNodeId&lt;span style="color:#f92672">)&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">val&lt;/span> jobVertex &lt;span style="color:#66d9ef">=&lt;/span> &lt;span style="color:#66d9ef">new&lt;/span> &lt;span style="color:#a6e22e">JobVertex&lt;/span>&lt;span style="color:#f92672">(&lt;/span>streamNode&lt;span style="color:#f92672">.&lt;/span>getOperatorName&lt;span style="color:#f92672">)&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e">// 1. 设置调用类
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span> jobVertex&lt;span style="color:#f92672">.&lt;/span>setInvokableClass&lt;span style="color:#f92672">(&lt;/span>classOf&lt;span style="color:#f92672">[&lt;/span>&lt;span style="color:#66d9ef">StreamTask&lt;/span>&lt;span style="color:#f92672">[&lt;/span>&lt;span style="color:#66d9ef">_&lt;/span>, &lt;span style="color:#66d9ef">_&lt;/span>&lt;span style="color:#f92672">]])&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e">// 2. 设置并行度
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span> jobVertex&lt;span style="color:#f92672">.&lt;/span>setParallelism&lt;span style="color:#f92672">(&lt;/span>streamNode&lt;span style="color:#f92672">.&lt;/span>getParallelism&lt;span style="color:#f92672">)&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e">// 3. 设置最大并行度
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span> &lt;span style="color:#66d9ef">if&lt;/span> &lt;span style="color:#f92672">(&lt;/span>streamNode&lt;span style="color:#f92672">.&lt;/span>getMaxParallelism &lt;span style="color:#f92672">&amp;gt;&lt;/span> &lt;span style="color:#ae81ff">0&lt;/span>&lt;span style="color:#f92672">)&lt;/span> &lt;span style="color:#f92672">{&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> jobVertex&lt;span style="color:#f92672">.&lt;/span>setMaxParallelism&lt;span style="color:#f92672">(&lt;/span>streamNode&lt;span style="color:#f92672">.&lt;/span>getMaxParallelism&lt;span style="color:#f92672">)&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">}&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e">// 4. 设置资源需求
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span> &lt;span style="color:#66d9ef">if&lt;/span> &lt;span style="color:#f92672">(&lt;/span>streamNode&lt;span style="color:#f92672">.&lt;/span>getMinResources &lt;span style="color:#f92672">!=&lt;/span> &lt;span style="color:#66d9ef">null&lt;/span>&lt;span style="color:#f92672">)&lt;/span> &lt;span style="color:#f92672">{&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> jobVertex&lt;span style="color:#f92672">.&lt;/span>setResources&lt;span style="color:#f92672">(&lt;/span>streamNode&lt;span style="color:#f92672">.&lt;/span>getMinResources&lt;span style="color:#f92672">,&lt;/span> streamNode&lt;span style="color:#f92672">.&lt;/span>getPreferredResources&lt;span style="color:#f92672">)&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">}&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e">// 5. 配置StreamConfig
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span> &lt;span style="color:#66d9ef">val&lt;/span> config &lt;span style="color:#66d9ef">=&lt;/span> &lt;span style="color:#66d9ef">new&lt;/span> &lt;span style="color:#a6e22e">StreamConfig&lt;/span>&lt;span style="color:#f92672">(&lt;/span>jobVertex&lt;span style="color:#f92672">.&lt;/span>getConfiguration&lt;span style="color:#f92672">)&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> setVertexConfig&lt;span style="color:#f92672">(&lt;/span>streamNodeId&lt;span style="color:#f92672">,&lt;/span> config&lt;span style="color:#f92672">,&lt;/span> chainedSources&lt;span style="color:#f92672">,&lt;/span> chainedOutputs&lt;span style="color:#f92672">)&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> jobGraph&lt;span style="color:#f92672">.&lt;/span>addVertex&lt;span style="color:#f92672">(&lt;/span>jobVertex&lt;span style="color:#f92672">)&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> jobVertices&lt;span style="color:#f92672">.&lt;/span>put&lt;span style="color:#f92672">(&lt;/span>streamNodeId&lt;span style="color:#f92672">,&lt;/span> jobVertex&lt;span style="color:#f92672">)&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> jobVertex
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">}&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f92672">}&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h3 id="23-executiongraph创建">2.3 ExecutionGraph创建&lt;/h3>
&lt;h4 id="executiongraph构建流程图">ExecutionGraph构建流程图&lt;/h4>
&lt;div class="mermaid">graph TD
A[JobGraph] --> B[ExecutionGraphBuilder]
B --> C[创建ExecutionJobVertex]
C --> D[创建ExecutionVertex]
D --> E[创建Execution]
E --> F[分析数据流依赖]
F --> G[创建IntermediateResult]
G --> H[连接ExecutionEdge]
H --> I[配置调度约束]
I --> J[ExecutionGraph完成]
C --> C1[设置并行度]
C1 --> C2[分配Slot共享组]
C2 --> C3[设置Co-location约束]
C3 --> D
style A fill:#e1f5fe
style B fill:#fff3e0
style J fill:#e8f5e8
&lt;/div>
&lt;h4 id="executiongraph构建源码">ExecutionGraph构建源码&lt;/h4>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-scala" data-lang="scala">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">// ExecutionGraphBuilder.scala - ExecutionGraph构建器
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>&lt;span style="color:#66d9ef">object&lt;/span> &lt;span style="color:#a6e22e">ExecutionGraphBuilder&lt;/span> &lt;span style="color:#f92672">{&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e">// 从JobGraph构建ExecutionGraph的主要方法
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span> &lt;span style="color:#66d9ef">def&lt;/span> buildGraph&lt;span style="color:#f92672">(&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> jobGraph&lt;span style="color:#66d9ef">:&lt;/span> &lt;span style="color:#66d9ef">JobGraph&lt;/span>&lt;span style="color:#f92672">,&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> configuration&lt;span style="color:#66d9ef">:&lt;/span> &lt;span style="color:#66d9ef">Configuration&lt;/span>&lt;span style="color:#f92672">,&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> futureExecutor&lt;span style="color:#66d9ef">:&lt;/span> &lt;span style="color:#66d9ef">ScheduledExecutorService&lt;/span>&lt;span style="color:#f92672">,&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> ioExecutor&lt;span style="color:#66d9ef">:&lt;/span> &lt;span style="color:#66d9ef">Executor&lt;/span>&lt;span style="color:#f92672">,&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> userCodeClassLoader&lt;span style="color:#66d9ef">:&lt;/span> &lt;span style="color:#66d9ef">ClassLoader&lt;/span>&lt;span style="color:#f92672">,&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> checkpointRecoveryFactory&lt;span style="color:#66d9ef">:&lt;/span> &lt;span style="color:#66d9ef">CompletedCheckpointStore&lt;/span>&lt;span style="color:#f92672">,&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> rpcTimeout&lt;span style="color:#66d9ef">:&lt;/span> &lt;span style="color:#66d9ef">Time&lt;/span>&lt;span style="color:#f92672">,&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> blobWriter&lt;span style="color:#66d9ef">:&lt;/span> &lt;span style="color:#66d9ef">BlobWriter&lt;/span>&lt;span style="color:#f92672">,&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> log&lt;span style="color:#66d9ef">:&lt;/span> &lt;span style="color:#66d9ef">Logger&lt;/span>&lt;span style="color:#f92672">)&lt;/span>&lt;span style="color:#66d9ef">:&lt;/span> &lt;span style="color:#66d9ef">ExecutionGraph&lt;/span> &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#f92672">{&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e">// 1. 创建ExecutionGraph实例
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span> &lt;span style="color:#66d9ef">val&lt;/span> executionGraph &lt;span style="color:#66d9ef">=&lt;/span> &lt;span style="color:#66d9ef">new&lt;/span> &lt;span style="color:#a6e22e">ExecutionGraph&lt;/span>&lt;span style="color:#f92672">(&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> jobGraph&lt;span style="color:#f92672">.&lt;/span>getJobID&lt;span style="color:#f92672">,&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> jobGraph&lt;span style="color:#f92672">.&lt;/span>getName&lt;span style="color:#f92672">,&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> jobGraph&lt;span style="color:#f92672">.&lt;/span>getJobConfiguration&lt;span style="color:#f92672">,&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> futureExecutor&lt;span style="color:#f92672">,&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> ioExecutor&lt;span style="color:#f92672">,&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> rpcTimeout&lt;span style="color:#f92672">,&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> checkpointRecoveryFactory&lt;span style="color:#f92672">,&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> userCodeClassLoader&lt;span style="color:#f92672">)&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">try&lt;/span> &lt;span style="color:#f92672">{&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e">// 2. 设置调度模式
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span> executionGraph&lt;span style="color:#f92672">.&lt;/span>setScheduleMode&lt;span style="color:#f92672">(&lt;/span>jobGraph&lt;span style="color:#f92672">.&lt;/span>getScheduleMode&lt;span style="color:#f92672">)&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e">// 3. 设置JSON计划
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span> executionGraph&lt;span style="color:#f92672">.&lt;/span>setJsonPlan&lt;span style="color:#f92672">(&lt;/span>&lt;span style="color:#a6e22e">JsonPlanGenerator&lt;/span>&lt;span style="color:#f92672">.&lt;/span>generatePlan&lt;span style="color:#f92672">(&lt;/span>jobGraph&lt;span style="color:#f92672">))&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e">// 4. 构建ExecutionJobVertex
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span> &lt;span style="color:#66d9ef">val&lt;/span> sortedTopology &lt;span style="color:#66d9ef">=&lt;/span> jobGraph&lt;span style="color:#f92672">.&lt;/span>getVerticesSortedTopologicallyFromSources
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">for&lt;/span> &lt;span style="color:#f92672">(&lt;/span>jobVertex &lt;span style="color:#66d9ef">&amp;lt;-&lt;/span> sortedTopology&lt;span style="color:#f92672">.&lt;/span>asScala&lt;span style="color:#f92672">)&lt;/span> &lt;span style="color:#f92672">{&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">val&lt;/span> executionJobVertex &lt;span style="color:#66d9ef">=&lt;/span> createExecutionJobVertex&lt;span style="color:#f92672">(&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> executionGraph&lt;span style="color:#f92672">,&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> jobVertex&lt;span style="color:#f92672">,&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> userCodeClassLoader&lt;span style="color:#f92672">,&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> log&lt;span style="color:#f92672">)&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> executionGraph&lt;span style="color:#f92672">.&lt;/span>attachJobVertex&lt;span style="color:#f92672">(&lt;/span>executionJobVertex&lt;span style="color:#f92672">)&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">}&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e">// 5. 连接ExecutionJobVertex之间的边
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span> connectExecutionJobVertices&lt;span style="color:#f92672">(&lt;/span>executionGraph&lt;span style="color:#f92672">,&lt;/span> sortedTopology&lt;span style="color:#f92672">,&lt;/span> log&lt;span style="color:#f92672">)&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e">// 6. 配置检查点
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span> configureCheckpointing&lt;span style="color:#f92672">(&lt;/span>executionGraph&lt;span style="color:#f92672">,&lt;/span> jobGraph&lt;span style="color:#f92672">,&lt;/span> log&lt;span style="color:#f92672">)&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e">// 7. 配置Slot共享和Co-location
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span> configureSlotSharingAndCoLocation&lt;span style="color:#f92672">(&lt;/span>executionGraph&lt;span style="color:#f92672">,&lt;/span> jobGraph&lt;span style="color:#f92672">)&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> executionGraph
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">}&lt;/span> &lt;span style="color:#66d9ef">catch&lt;/span> &lt;span style="color:#f92672">{&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">case&lt;/span> e&lt;span style="color:#66d9ef">:&lt;/span> &lt;span style="color:#66d9ef">Exception&lt;/span> &lt;span style="color:#f92672">=&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> log&lt;span style="color:#f92672">.&lt;/span>error&lt;span style="color:#f92672">(&lt;/span>&lt;span style="color:#e6db74">s&amp;#34;Failed to build ExecutionGraph from JobGraph &lt;/span>&lt;span style="color:#e6db74">${&lt;/span>jobGraph&lt;span style="color:#f92672">.&lt;/span>getJobID&lt;span style="color:#e6db74">}&lt;/span>&lt;span style="color:#e6db74">&amp;#34;&lt;/span>&lt;span style="color:#f92672">,&lt;/span> e&lt;span style="color:#f92672">)&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">throw&lt;/span> &lt;span style="color:#66d9ef">new&lt;/span> &lt;span style="color:#a6e22e">JobException&lt;/span>&lt;span style="color:#f92672">(&lt;/span>&lt;span style="color:#e6db74">&amp;#34;Failed to build ExecutionGraph&amp;#34;&lt;/span>&lt;span style="color:#f92672">,&lt;/span> e&lt;span style="color:#f92672">)&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">}&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">}&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e">// 创建ExecutionJobVertex
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span> &lt;span style="color:#66d9ef">private&lt;/span> &lt;span style="color:#66d9ef">def&lt;/span> createExecutionJobVertex&lt;span style="color:#f92672">(&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> executionGraph&lt;span style="color:#66d9ef">:&lt;/span> &lt;span style="color:#66d9ef">ExecutionGraph&lt;/span>&lt;span style="color:#f92672">,&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> jobVertex&lt;span style="color:#66d9ef">:&lt;/span> &lt;span style="color:#66d9ef">JobVertex&lt;/span>&lt;span style="color:#f92672">,&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> userCodeClassLoader&lt;span style="color:#66d9ef">:&lt;/span> &lt;span style="color:#66d9ef">ClassLoader&lt;/span>&lt;span style="color:#f92672">,&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> log&lt;span style="color:#66d9ef">:&lt;/span> &lt;span style="color:#66d9ef">Logger&lt;/span>&lt;span style="color:#f92672">)&lt;/span>&lt;span style="color:#66d9ef">:&lt;/span> &lt;span style="color:#66d9ef">ExecutionJobVertex&lt;/span> &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#f92672">{&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e">// 1. 创建ExecutionJobVertex
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span> &lt;span style="color:#66d9ef">val&lt;/span> executionJobVertex &lt;span style="color:#66d9ef">=&lt;/span> &lt;span style="color:#66d9ef">new&lt;/span> &lt;span style="color:#a6e22e">ExecutionJobVertex&lt;/span>&lt;span style="color:#f92672">(&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> executionGraph&lt;span style="color:#f92672">,&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> jobVertex&lt;span style="color:#f92672">,&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> jobVertex&lt;span style="color:#f92672">.&lt;/span>getParallelism&lt;span style="color:#f92672">,&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> jobVertex&lt;span style="color:#f92672">.&lt;/span>getMaxParallelism&lt;span style="color:#f92672">,&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> userCodeClassLoader&lt;span style="color:#f92672">)&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e">// 2. 创建ExecutionVertex数组
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span> &lt;span style="color:#66d9ef">val&lt;/span> parallelism &lt;span style="color:#66d9ef">=&lt;/span> jobVertex&lt;span style="color:#f92672">.&lt;/span>getParallelism
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">val&lt;/span> taskVertices &lt;span style="color:#66d9ef">=&lt;/span> &lt;span style="color:#66d9ef">new&lt;/span> &lt;span style="color:#a6e22e">Array&lt;/span>&lt;span style="color:#f92672">[&lt;/span>&lt;span style="color:#66d9ef">ExecutionVertex&lt;/span>&lt;span style="color:#f92672">](&lt;/span>parallelism&lt;span style="color:#f92672">)&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">for&lt;/span> &lt;span style="color:#f92672">(&lt;/span>i &lt;span style="color:#66d9ef">&amp;lt;-&lt;/span> &lt;span style="color:#ae81ff">0&lt;/span> until parallelism&lt;span style="color:#f92672">)&lt;/span> &lt;span style="color:#f92672">{&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> taskVertices&lt;span style="color:#f92672">(&lt;/span>i&lt;span style="color:#f92672">)&lt;/span> &lt;span style="color:#66d9ef">=&lt;/span> &lt;span style="color:#66d9ef">new&lt;/span> &lt;span style="color:#a6e22e">ExecutionVertex&lt;/span>&lt;span style="color:#f92672">(&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> executionJobVertex&lt;span style="color:#f92672">,&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> i&lt;span style="color:#f92672">,&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> createIntermediateResults&lt;span style="color:#f92672">(&lt;/span>jobVertex&lt;span style="color:#f92672">,&lt;/span> i&lt;span style="color:#f92672">),&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> rpcTimeout&lt;span style="color:#f92672">)&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">}&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> executionJobVertex&lt;span style="color:#f92672">.&lt;/span>setTaskVertices&lt;span style="color:#f92672">(&lt;/span>taskVertices&lt;span style="color:#f92672">)&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e">// 3. 初始化算子坐标器（如果需要）
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span> &lt;span style="color:#66d9ef">val&lt;/span> coordinatorClassName &lt;span style="color:#66d9ef">=&lt;/span> jobVertex&lt;span style="color:#f92672">.&lt;/span>getOperatorCoordinatorClassName
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">if&lt;/span> &lt;span style="color:#f92672">(&lt;/span>coordinatorClassName &lt;span style="color:#f92672">!=&lt;/span> &lt;span style="color:#66d9ef">null&lt;/span>&lt;span style="color:#f92672">)&lt;/span> &lt;span style="color:#f92672">{&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">val&lt;/span> coordinatorFactory &lt;span style="color:#66d9ef">=&lt;/span> createOperatorCoordinatorFactory&lt;span style="color:#f92672">(&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> coordinatorClassName&lt;span style="color:#f92672">,&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> userCodeClassLoader&lt;span style="color:#f92672">)&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> executionJobVertex&lt;span style="color:#f92672">.&lt;/span>setOperatorCoordinatorFactory&lt;span style="color:#f92672">(&lt;/span>coordinatorFactory&lt;span style="color:#f92672">)&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">}&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> executionJobVertex
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">}&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e">// 连接ExecutionJobVertex之间的边
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span> &lt;span style="color:#66d9ef">private&lt;/span> &lt;span style="color:#66d9ef">def&lt;/span> connectExecutionJobVertices&lt;span style="color:#f92672">(&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> executionGraph&lt;span style="color:#66d9ef">:&lt;/span> &lt;span style="color:#66d9ef">ExecutionGraph&lt;/span>&lt;span style="color:#f92672">,&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> sortedTopology&lt;span style="color:#66d9ef">:&lt;/span> &lt;span style="color:#66d9ef">util.List&lt;/span>&lt;span style="color:#f92672">[&lt;/span>&lt;span style="color:#66d9ef">JobVertex&lt;/span>&lt;span style="color:#f92672">],&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> log&lt;span style="color:#66d9ef">:&lt;/span> &lt;span style="color:#66d9ef">Logger&lt;/span>&lt;span style="color:#f92672">)&lt;/span>&lt;span style="color:#66d9ef">:&lt;/span> &lt;span style="color:#66d9ef">Unit&lt;/span> &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#f92672">{&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">for&lt;/span> &lt;span style="color:#f92672">(&lt;/span>jobVertex &lt;span style="color:#66d9ef">&amp;lt;-&lt;/span> sortedTopology&lt;span style="color:#f92672">.&lt;/span>asScala&lt;span style="color:#f92672">)&lt;/span> &lt;span style="color:#f92672">{&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">val&lt;/span> executionJobVertex &lt;span style="color:#66d9ef">=&lt;/span> executionGraph&lt;span style="color:#f92672">.&lt;/span>getJobVertex&lt;span style="color:#f92672">(&lt;/span>jobVertex&lt;span style="color:#f92672">.&lt;/span>getID&lt;span style="color:#f92672">)&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e">// 处理每个输入
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span> &lt;span style="color:#66d9ef">for&lt;/span> &lt;span style="color:#f92672">(&lt;/span>i &lt;span style="color:#66d9ef">&amp;lt;-&lt;/span> &lt;span style="color:#ae81ff">0&lt;/span> until jobVertex&lt;span style="color:#f92672">.&lt;/span>getNumberOfInputs&lt;span style="color:#f92672">)&lt;/span> &lt;span style="color:#f92672">{&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">val&lt;/span> jobEdge &lt;span style="color:#66d9ef">=&lt;/span> jobVertex&lt;span style="color:#f92672">.&lt;/span>getInputs&lt;span style="color:#f92672">.&lt;/span>get&lt;span style="color:#f92672">(&lt;/span>i&lt;span style="color:#f92672">)&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">val&lt;/span> sourceJobVertex &lt;span style="color:#66d9ef">=&lt;/span> jobEdge&lt;span style="color:#f92672">.&lt;/span>getSource&lt;span style="color:#f92672">.&lt;/span>getProducer
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">val&lt;/span> sourceExecutionJobVertex &lt;span style="color:#66d9ef">=&lt;/span> executionGraph&lt;span style="color:#f92672">.&lt;/span>getJobVertex&lt;span style="color:#f92672">(&lt;/span>sourceJobVertex&lt;span style="color:#f92672">.&lt;/span>getID&lt;span style="color:#f92672">)&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e">// 创建ExecutionEdge
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span> connectJobVertices&lt;span style="color:#f92672">(&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> sourceExecutionJobVertex&lt;span style="color:#f92672">,&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> executionJobVertex&lt;span style="color:#f92672">,&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> jobEdge&lt;span style="color:#f92672">,&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> log&lt;span style="color:#f92672">)&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">}&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">}&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">}&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e">// 连接两个ExecutionJobVertex
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span> &lt;span style="color:#66d9ef">private&lt;/span> &lt;span style="color:#66d9ef">def&lt;/span> connectJobVertices&lt;span style="color:#f92672">(&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> sourceJobVertex&lt;span style="color:#66d9ef">:&lt;/span> &lt;span style="color:#66d9ef">ExecutionJobVertex&lt;/span>&lt;span style="color:#f92672">,&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> targetJobVertex&lt;span style="color:#66d9ef">:&lt;/span> &lt;span style="color:#66d9ef">ExecutionJobVertex&lt;/span>&lt;span style="color:#f92672">,&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> jobEdge&lt;span style="color:#66d9ef">:&lt;/span> &lt;span style="color:#66d9ef">JobEdge&lt;/span>&lt;span style="color:#f92672">,&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> log&lt;span style="color:#66d9ef">:&lt;/span> &lt;span style="color:#66d9ef">Logger&lt;/span>&lt;span style="color:#f92672">)&lt;/span>&lt;span style="color:#66d9ef">:&lt;/span> &lt;span style="color:#66d9ef">Unit&lt;/span> &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#f92672">{&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">val&lt;/span> sourceIntermediateResult &lt;span style="color:#66d9ef">=&lt;/span> sourceJobVertex&lt;span style="color:#f92672">.&lt;/span>getProducedDataSets&lt;span style="color:#f92672">()(&lt;/span>jobEdge&lt;span style="color:#f92672">.&lt;/span>getSourceIndex&lt;span style="color:#f92672">)&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">val&lt;/span> targetIntermediateDataSet &lt;span style="color:#66d9ef">=&lt;/span> targetJobVertex&lt;span style="color:#f92672">.&lt;/span>getInputs&lt;span style="color:#f92672">.&lt;/span>get&lt;span style="color:#f92672">(&lt;/span>jobEdge&lt;span style="color:#f92672">.&lt;/span>getTargetIndex&lt;span style="color:#f92672">)&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e">// 连接中间结果
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span> targetIntermediateDataSet&lt;span style="color:#f92672">.&lt;/span>setSource&lt;span style="color:#f92672">(&lt;/span>sourceIntermediateResult&lt;span style="color:#f92672">)&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e">// 根据分发模式创建ExecutionEdge
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span> &lt;span style="color:#66d9ef">val&lt;/span> distributionPattern &lt;span style="color:#66d9ef">=&lt;/span> jobEdge&lt;span style="color:#f92672">.&lt;/span>getDistributionPattern
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> distributionPattern &lt;span style="color:#66d9ef">match&lt;/span> &lt;span style="color:#f92672">{&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">case&lt;/span> &lt;span style="color:#a6e22e">DistributionPattern&lt;/span>&lt;span style="color:#f92672">.&lt;/span>&lt;span style="color:#a6e22e">POINTWISE&lt;/span> &lt;span style="color:#66d9ef">=&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> connectPointwise&lt;span style="color:#f92672">(&lt;/span>sourceJobVertex&lt;span style="color:#f92672">,&lt;/span> targetJobVertex&lt;span style="color:#f92672">,&lt;/span> sourceIntermediateResult&lt;span style="color:#f92672">)&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">case&lt;/span> &lt;span style="color:#a6e22e">DistributionPattern&lt;/span>&lt;span style="color:#f92672">.&lt;/span>&lt;span style="color:#a6e22e">ALL_TO_ALL&lt;/span> &lt;span style="color:#66d9ef">=&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> connectAllToAll&lt;span style="color:#f92672">(&lt;/span>sourceJobVertex&lt;span style="color:#f92672">,&lt;/span> targetJobVertex&lt;span style="color:#f92672">,&lt;/span> sourceIntermediateResult&lt;span style="color:#f92672">)&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">case&lt;/span> &lt;span style="color:#66d9ef">_&lt;/span> &lt;span style="color:#66d9ef">=&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">throw&lt;/span> &lt;span style="color:#66d9ef">new&lt;/span> &lt;span style="color:#a6e22e">IllegalStateException&lt;/span>&lt;span style="color:#f92672">(&lt;/span>&lt;span style="color:#e6db74">s&amp;#34;Unknown distribution pattern: &lt;/span>&lt;span style="color:#e6db74">$distributionPattern&lt;/span>&lt;span style="color:#e6db74">&amp;#34;&lt;/span>&lt;span style="color:#f92672">)&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">}&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">}&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e">// 点对点连接模式
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span> &lt;span style="color:#66d9ef">private&lt;/span> &lt;span style="color:#66d9ef">def&lt;/span> connectPointwise&lt;span style="color:#f92672">(&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> sourceJobVertex&lt;span style="color:#66d9ef">:&lt;/span> &lt;span style="color:#66d9ef">ExecutionJobVertex&lt;/span>&lt;span style="color:#f92672">,&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> targetJobVertex&lt;span style="color:#66d9ef">:&lt;/span> &lt;span style="color:#66d9ef">ExecutionJobVertex&lt;/span>&lt;span style="color:#f92672">,&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> intermediateResult&lt;span style="color:#66d9ef">:&lt;/span> &lt;span style="color:#66d9ef">IntermediateResult&lt;/span>&lt;span style="color:#f92672">)&lt;/span>&lt;span style="color:#66d9ef">:&lt;/span> &lt;span style="color:#66d9ef">Unit&lt;/span> &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#f92672">{&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">val&lt;/span> sourceParallelism &lt;span style="color:#66d9ef">=&lt;/span> sourceJobVertex&lt;span style="color:#f92672">.&lt;/span>getParallelism
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">val&lt;/span> targetParallelism &lt;span style="color:#66d9ef">=&lt;/span> targetJobVertex&lt;span style="color:#f92672">.&lt;/span>getParallelism
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> require&lt;span style="color:#f92672">(&lt;/span>sourceParallelism &lt;span style="color:#f92672">==&lt;/span> targetParallelism&lt;span style="color:#f92672">,&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e6db74">&amp;#34;Pointwise connection requires same parallelism&amp;#34;&lt;/span>&lt;span style="color:#f92672">)&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">for&lt;/span> &lt;span style="color:#f92672">(&lt;/span>i &lt;span style="color:#66d9ef">&amp;lt;-&lt;/span> &lt;span style="color:#ae81ff">0&lt;/span> until sourceParallelism&lt;span style="color:#f92672">)&lt;/span> &lt;span style="color:#f92672">{&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">val&lt;/span> sourceVertex &lt;span style="color:#66d9ef">=&lt;/span> sourceJobVertex&lt;span style="color:#f92672">.&lt;/span>getTaskVertices&lt;span style="color:#f92672">()(&lt;/span>i&lt;span style="color:#f92672">)&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">val&lt;/span> targetVertex &lt;span style="color:#66d9ef">=&lt;/span> targetJobVertex&lt;span style="color:#f92672">.&lt;/span>getTaskVertices&lt;span style="color:#f92672">()(&lt;/span>i&lt;span style="color:#f92672">)&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">val&lt;/span> resultPartition &lt;span style="color:#66d9ef">=&lt;/span> intermediateResult&lt;span style="color:#f92672">.&lt;/span>getPartitions&lt;span style="color:#f92672">()(&lt;/span>i&lt;span style="color:#f92672">)&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">val&lt;/span> inputGate &lt;span style="color:#66d9ef">=&lt;/span> &lt;span style="color:#66d9ef">new&lt;/span> &lt;span style="color:#a6e22e">IntermediateResultPartition&lt;/span>&lt;span style="color:#f92672">(&lt;/span>resultPartition&lt;span style="color:#f92672">)&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">val&lt;/span> executionEdge &lt;span style="color:#66d9ef">=&lt;/span> &lt;span style="color:#66d9ef">new&lt;/span> &lt;span style="color:#a6e22e">ExecutionEdge&lt;/span>&lt;span style="color:#f92672">(&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> sourceVertex&lt;span style="color:#f92672">,&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> targetVertex&lt;span style="color:#f92672">,&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> resultPartition&lt;span style="color:#f92672">,&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> inputGate&lt;span style="color:#f92672">)&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> targetVertex&lt;span style="color:#f92672">.&lt;/span>addInputSource&lt;span style="color:#f92672">(&lt;/span>executionEdge&lt;span style="color:#f92672">)&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">}&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">}&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e">// 全连接模式
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span> &lt;span style="color:#66d9ef">private&lt;/span> &lt;span style="color:#66d9ef">def&lt;/span> connectAllToAll&lt;span style="color:#f92672">(&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> sourceJobVertex&lt;span style="color:#66d9ef">:&lt;/span> &lt;span style="color:#66d9ef">ExecutionJobVertex&lt;/span>&lt;span style="color:#f92672">,&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> targetJobVertex&lt;span style="color:#66d9ef">:&lt;/span> &lt;span style="color:#66d9ef">ExecutionJobVertex&lt;/span>&lt;span style="color:#f92672">,&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> intermediateResult&lt;span style="color:#66d9ef">:&lt;/span> &lt;span style="color:#66d9ef">IntermediateResult&lt;/span>&lt;span style="color:#f92672">)&lt;/span>&lt;span style="color:#66d9ef">:&lt;/span> &lt;span style="color:#66d9ef">Unit&lt;/span> &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#f92672">{&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">val&lt;/span> sourceParallelism &lt;span style="color:#66d9ef">=&lt;/span> sourceJobVertex&lt;span style="color:#f92672">.&lt;/span>getParallelism
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">val&lt;/span> targetParallelism &lt;span style="color:#66d9ef">=&lt;/span> targetJobVertex&lt;span style="color:#f92672">.&lt;/span>getParallelism
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">for&lt;/span> &lt;span style="color:#f92672">(&lt;/span>i &lt;span style="color:#66d9ef">&amp;lt;-&lt;/span> &lt;span style="color:#ae81ff">0&lt;/span> until targetParallelism&lt;span style="color:#f92672">)&lt;/span> &lt;span style="color:#f92672">{&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">val&lt;/span> targetVertex &lt;span style="color:#66d9ef">=&lt;/span> targetJobVertex&lt;span style="color:#f92672">.&lt;/span>getTaskVertices&lt;span style="color:#f92672">()(&lt;/span>i&lt;span style="color:#f92672">)&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">for&lt;/span> &lt;span style="color:#f92672">(&lt;/span>j &lt;span style="color:#66d9ef">&amp;lt;-&lt;/span> &lt;span style="color:#ae81ff">0&lt;/span> until sourceParallelism&lt;span style="color:#f92672">)&lt;/span> &lt;span style="color:#f92672">{&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">val&lt;/span> sourceVertex &lt;span style="color:#66d9ef">=&lt;/span> sourceJobVertex&lt;span style="color:#f92672">.&lt;/span>getTaskVertices&lt;span style="color:#f92672">()(&lt;/span>j&lt;span style="color:#f92672">)&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">val&lt;/span> resultPartition &lt;span style="color:#66d9ef">=&lt;/span> intermediateResult&lt;span style="color:#f92672">.&lt;/span>getPartitions&lt;span style="color:#f92672">()(&lt;/span>j&lt;span style="color:#f92672">)&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">val&lt;/span> inputGate &lt;span style="color:#66d9ef">=&lt;/span> &lt;span style="color:#66d9ef">new&lt;/span> &lt;span style="color:#a6e22e">IntermediateResultPartition&lt;/span>&lt;span style="color:#f92672">(&lt;/span>resultPartition&lt;span style="color:#f92672">)&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">val&lt;/span> executionEdge &lt;span style="color:#66d9ef">=&lt;/span> &lt;span style="color:#66d9ef">new&lt;/span> &lt;span style="color:#a6e22e">ExecutionEdge&lt;/span>&lt;span style="color:#f92672">(&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> sourceVertex&lt;span style="color:#f92672">,&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> targetVertex&lt;span style="color:#f92672">,&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> resultPartition&lt;span style="color:#f92672">,&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> inputGate&lt;span style="color:#f92672">)&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> targetVertex&lt;span style="color:#f92672">.&lt;/span>addInputSource&lt;span style="color:#f92672">(&lt;/span>executionEdge&lt;span style="color:#f92672">)&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">}&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">}&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">}&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f92672">}&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h3 id="24-物理图部署">2.4 物理图部署&lt;/h3>
&lt;h4 id="物理部署流程图">物理部署流程图&lt;/h4>
&lt;div class="mermaid">graph TD
A[ExecutionGraph] --> B[调度器启动]
B --> C[分配Slot资源]
C --> D[创建TaskDeploymentDescriptor]
D --> E[发送部署请求到TaskManager]
E --> F[TaskManager创建Task]
F --> G[初始化算子]
G --> H[连接网络通道]
H --> I[启动Task执行]
I --> J[报告任务状态]
C --> C1[请求Slot]
C1 --> C2[分配物理资源]
C2 --> C3[建立网络连接]
C3 --> D
style A fill:#e1f5fe
style D fill:#fff3e0
style I fill:#e8f5e8
style J fill:#c8e6c9
&lt;/div>
&lt;hr>
&lt;h2 id="三任务调度系统-1">三、任务调度系统&lt;/h2>
&lt;h3 id="31-调度器架构">3.1 调度器架构&lt;/h3>
&lt;h4 id="flink调度器架构图">Flink调度器架构图&lt;/h4>
&lt;div class="mermaid">graph TD
A[JobMaster] --> B[SchedulerNG调度器]
B --> C[ExecutionSlotAllocator]
B --> D[ExecutionVertexSchedulingRequirementsProvider]
B --> E[ExecutionFailureHandler]
C --> F[SlotProvider]
F --> G[ResourceManager]
G --> H[TaskManager资源池]
B --> I[DefaultScheduler]
I --> J[SchedulingStrategy调度策略]
J --> K[EagerSchedulingStrategy]
J --> L[LazyFromSourcesSchedulingStrategy]
J --> M[PipelinedRegionSchedulingStrategy]
style A fill:#e1f5fe
style B fill:#fff3e0
style I fill:#e8f5e8
style J fill:#ffebee
&lt;/div>
&lt;h4 id="调度器核心源码">调度器核心源码&lt;/h4>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-scala" data-lang="scala">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">// DefaultScheduler.scala - 默认调度器实现
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>&lt;span style="color:#66d9ef">class&lt;/span> &lt;span style="color:#a6e22e">DefaultScheduler&lt;/span>&lt;span style="color:#f92672">(&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> log&lt;span style="color:#66d9ef">:&lt;/span> &lt;span style="color:#66d9ef">Logger&lt;/span>&lt;span style="color:#f92672">,&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> jobGraph&lt;span style="color:#66d9ef">:&lt;/span> &lt;span style="color:#66d9ef">JobGraph&lt;/span>&lt;span style="color:#f92672">,&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> backtrackingStateStore&lt;span style="color:#66d9ef">:&lt;/span> &lt;span style="color:#66d9ef">BacktrackingStateStore&lt;/span>&lt;span style="color:#f92672">,&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> ioExecutor&lt;span style="color:#66d9ef">:&lt;/span> &lt;span style="color:#66d9ef">Executor&lt;/span>&lt;span style="color:#f92672">,&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> jobMasterConfiguration&lt;span style="color:#66d9ef">:&lt;/span> &lt;span style="color:#66d9ef">Configuration&lt;/span>&lt;span style="color:#f92672">,&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> slotProvider&lt;span style="color:#66d9ef">:&lt;/span> &lt;span style="color:#66d9ef">SlotProvider&lt;/span>&lt;span style="color:#f92672">,&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> scheduledExecutorService&lt;span style="color:#66d9ef">:&lt;/span> &lt;span style="color:#66d9ef">ScheduledExecutorService&lt;/span>&lt;span style="color:#f92672">,&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> userCodeLoader&lt;span style="color:#66d9ef">:&lt;/span> &lt;span style="color:#66d9ef">ClassLoader&lt;/span>&lt;span style="color:#f92672">,&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> checkpointCleaner&lt;span style="color:#66d9ef">:&lt;/span> &lt;span style="color:#66d9ef">CheckpointCleaner&lt;/span>&lt;span style="color:#f92672">,&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> checkpointRecoveryFactory&lt;span style="color:#66d9ef">:&lt;/span> &lt;span style="color:#66d9ef">CompletedCheckpointStore&lt;/span>&lt;span style="color:#f92672">,&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> failureEnricher&lt;span style="color:#66d9ef">:&lt;/span> &lt;span style="color:#66d9ef">FailureEnricher&lt;/span>&lt;span style="color:#f92672">,&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> rpcTimeout&lt;span style="color:#66d9ef">:&lt;/span> &lt;span style="color:#66d9ef">Time&lt;/span>&lt;span style="color:#f92672">)&lt;/span> &lt;span style="color:#66d9ef">extends&lt;/span> &lt;span style="color:#a6e22e">SchedulerNG&lt;/span> &lt;span style="color:#f92672">{&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e">// 执行图
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span> &lt;span style="color:#66d9ef">private&lt;/span> &lt;span style="color:#66d9ef">val&lt;/span> executionGraph&lt;span style="color:#66d9ef">:&lt;/span> &lt;span style="color:#66d9ef">ExecutionGraph&lt;/span> &lt;span style="color:#f92672">=&lt;/span> createAndRestoreExecutionGraph&lt;span style="color:#f92672">()&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e">// 调度策略
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span> &lt;span style="color:#66d9ef">private&lt;/span> &lt;span style="color:#66d9ef">val&lt;/span> schedulingStrategy&lt;span style="color:#66d9ef">:&lt;/span> &lt;span style="color:#66d9ef">SchedulingStrategy&lt;/span> &lt;span style="color:#f92672">=&lt;/span> createSchedulingStrategy&lt;span style="color:#f92672">()&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e">// 失败处理器
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span> &lt;span style="color:#66d9ef">private&lt;/span> &lt;span style="color:#66d9ef">val&lt;/span> executionFailureHandler&lt;span style="color:#66d9ef">:&lt;/span> &lt;span style="color:#66d9ef">ExecutionFailureHandler&lt;/span> &lt;span style="color:#f92672">=&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">new&lt;/span> &lt;span style="color:#a6e22e">RestartPipelinedRegionFailureHandler&lt;/span>&lt;span style="color:#f92672">(&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> executionGraph&lt;span style="color:#f92672">,&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> schedulingStrategy&lt;span style="color:#f92672">,&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> backtrackingStateStore&lt;span style="color:#f92672">,&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> rpcTimeout&lt;span style="color:#f92672">,&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> log&lt;span style="color:#f92672">)&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e">// Slot分配器
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span> &lt;span style="color:#66d9ef">private&lt;/span> &lt;span style="color:#66d9ef">val&lt;/span> executionSlotAllocator&lt;span style="color:#66d9ef">:&lt;/span> &lt;span style="color:#66d9ef">ExecutionSlotAllocator&lt;/span> &lt;span style="color:#f92672">=&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">new&lt;/span> &lt;span style="color:#a6e22e">DefaultExecutionSlotAllocator&lt;/span>&lt;span style="color:#f92672">(&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> slotProvider&lt;span style="color:#f92672">,&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">new&lt;/span> &lt;span style="color:#a6e22e">DefaultPreferredLocationsRetriever&lt;/span>&lt;span style="color:#f92672">(&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">StateLocations&lt;/span>&lt;span style="color:#f92672">.&lt;/span>&lt;span style="color:#a6e22e">StateAssignmentOperation&lt;/span>&lt;span style="color:#f92672">.&lt;/span>&lt;span style="color:#a6e22e">LOAD&lt;/span>&lt;span style="color:#f92672">),&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> rpcTimeout&lt;span style="color:#f92672">)&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e">// 启动调度
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span> &lt;span style="color:#66d9ef">override&lt;/span> &lt;span style="color:#66d9ef">def&lt;/span> startScheduling&lt;span style="color:#f92672">()&lt;/span>&lt;span style="color:#66d9ef">:&lt;/span> &lt;span style="color:#66d9ef">Unit&lt;/span> &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#f92672">{&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> checkState&lt;span style="color:#f92672">(&lt;/span>schedulingStrategy &lt;span style="color:#f92672">!=&lt;/span> &lt;span style="color:#66d9ef">null&lt;/span>&lt;span style="color:#f92672">,&lt;/span> &lt;span style="color:#e6db74">&amp;#34;Scheduling strategy must be initialized&amp;#34;&lt;/span>&lt;span style="color:#f92672">)&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">try&lt;/span> &lt;span style="color:#f92672">{&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e">// 1. 准备执行图进行调度
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span> prepareExecutionGraphForNgScheduling&lt;span style="color:#f92672">()&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e">// 2. 启动检查点协调器
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span> startCheckpointScheduler&lt;span style="color:#f92672">()&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e">// 3. 开始调度执行
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span> schedulingStrategy&lt;span style="color:#f92672">.&lt;/span>startScheduling&lt;span style="color:#f92672">()&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> log&lt;span style="color:#f92672">.&lt;/span>info&lt;span style="color:#f92672">(&lt;/span>&lt;span style="color:#e6db74">&amp;#34;Started scheduling for job {}&amp;#34;&lt;/span>&lt;span style="color:#f92672">,&lt;/span> jobGraph&lt;span style="color:#f92672">.&lt;/span>getJobID&lt;span style="color:#f92672">)&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">}&lt;/span> &lt;span style="color:#66d9ef">catch&lt;/span> &lt;span style="color:#f92672">{&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">case&lt;/span> e&lt;span style="color:#66d9ef">:&lt;/span> &lt;span style="color:#66d9ef">Exception&lt;/span> &lt;span style="color:#f92672">=&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> log&lt;span style="color:#f92672">.&lt;/span>error&lt;span style="color:#f92672">(&lt;/span>&lt;span style="color:#e6db74">&amp;#34;Failed to start scheduling&amp;#34;&lt;/span>&lt;span style="color:#f92672">,&lt;/span> e&lt;span style="color:#f92672">)&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> failJob&lt;span style="color:#f92672">(&lt;/span>e&lt;span style="color:#f92672">)&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">}&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">}&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e">// 创建调度策略
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span> &lt;span style="color:#66d9ef">private&lt;/span> &lt;span style="color:#66d9ef">def&lt;/span> createSchedulingStrategy&lt;span style="color:#f92672">()&lt;/span>&lt;span style="color:#66d9ef">:&lt;/span> &lt;span style="color:#66d9ef">SchedulingStrategy&lt;/span> &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#f92672">{&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">val&lt;/span> schedulingStrategyFactory &lt;span style="color:#66d9ef">=&lt;/span> jobMasterConfiguration&lt;span style="color:#f92672">.&lt;/span>get&lt;span style="color:#f92672">(&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">JobManagerOptions&lt;/span>&lt;span style="color:#f92672">.&lt;/span>&lt;span style="color:#a6e22e">SCHEDULING_STRATEGY&lt;/span>&lt;span style="color:#f92672">)&lt;/span> &lt;span style="color:#66d9ef">match&lt;/span> &lt;span style="color:#f92672">{&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">case&lt;/span> &lt;span style="color:#e6db74">&amp;#34;eager&amp;#34;&lt;/span> &lt;span style="color:#66d9ef">=&amp;gt;&lt;/span> &lt;span style="color:#66d9ef">new&lt;/span> &lt;span style="color:#a6e22e">EagerSchedulingStrategy&lt;/span>&lt;span style="color:#f92672">.&lt;/span>&lt;span style="color:#a6e22e">Factory&lt;/span>&lt;span style="color:#f92672">()&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">case&lt;/span> &lt;span style="color:#e6db74">&amp;#34;lazy_from_sources&amp;#34;&lt;/span> &lt;span style="color:#66d9ef">=&amp;gt;&lt;/span> &lt;span style="color:#66d9ef">new&lt;/span> &lt;span style="color:#a6e22e">LazyFromSourcesSchedulingStrategy&lt;/span>&lt;span style="color:#f92672">.&lt;/span>&lt;span style="color:#a6e22e">Factory&lt;/span>&lt;span style="color:#f92672">()&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">case&lt;/span> &lt;span style="color:#e6db74">&amp;#34;pipelined_region&amp;#34;&lt;/span> &lt;span style="color:#66d9ef">=&amp;gt;&lt;/span> &lt;span style="color:#66d9ef">new&lt;/span> &lt;span style="color:#a6e22e">PipelinedRegionSchedulingStrategy&lt;/span>&lt;span style="color:#f92672">.&lt;/span>&lt;span style="color:#a6e22e">Factory&lt;/span>&lt;span style="color:#f92672">()&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">case&lt;/span> other &lt;span style="color:#66d9ef">=&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">throw&lt;/span> &lt;span style="color:#66d9ef">new&lt;/span> &lt;span style="color:#a6e22e">IllegalArgumentException&lt;/span>&lt;span style="color:#f92672">(&lt;/span>&lt;span style="color:#e6db74">s&amp;#34;Unknown scheduling strategy: &lt;/span>&lt;span style="color:#e6db74">$other&lt;/span>&lt;span style="color:#e6db74">&amp;#34;&lt;/span>&lt;span style="color:#f92672">)&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">}&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> schedulingStrategyFactory&lt;span style="color:#f92672">.&lt;/span>createInstance&lt;span style="color:#f92672">(&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">this&lt;/span>&lt;span style="color:#f92672">,&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> executionGraph&lt;span style="color:#f92672">,&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> executionSlotAllocator&lt;span style="color:#f92672">,&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> scheduledExecutorService&lt;span style="color:#f92672">)&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">}&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e">// 分配Slot并部署任务
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span> &lt;span style="color:#66d9ef">override&lt;/span> &lt;span style="color:#66d9ef">def&lt;/span> allocateSlotAndDeploy&lt;span style="color:#f92672">(&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> executionVertexId&lt;span style="color:#66d9ef">:&lt;/span> &lt;span style="color:#66d9ef">ExecutionVertexID&lt;/span>&lt;span style="color:#f92672">,&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> requiredSlotProfile&lt;span style="color:#66d9ef">:&lt;/span> &lt;span style="color:#66d9ef">SlotProfile&lt;/span>&lt;span style="color:#f92672">,&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> allowQueuedScheduling&lt;span style="color:#66d9ef">:&lt;/span> &lt;span style="color:#66d9ef">Boolean&lt;/span>&lt;span style="color:#f92672">)&lt;/span>&lt;span style="color:#66d9ef">:&lt;/span> &lt;span style="color:#66d9ef">CompletableFuture&lt;/span>&lt;span style="color:#f92672">[&lt;/span>&lt;span style="color:#66d9ef">Void&lt;/span>&lt;span style="color:#f92672">]&lt;/span> &lt;span style="color:#66d9ef">=&lt;/span> &lt;span style="color:#f92672">{&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e">// 1. 分配Slot
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span> &lt;span style="color:#66d9ef">val&lt;/span> slotAllocationFuture &lt;span style="color:#66d9ef">=&lt;/span> executionSlotAllocator&lt;span style="color:#f92672">.&lt;/span>allocateSlot&lt;span style="color:#f92672">(&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">new&lt;/span> &lt;span style="color:#a6e22e">ExecutionVertexSchedulingRequirements&lt;/span>&lt;span style="color:#f92672">.&lt;/span>&lt;span style="color:#a6e22e">Builder&lt;/span>&lt;span style="color:#f92672">()&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">.&lt;/span>withExecutionVertexId&lt;span style="color:#f92672">(&lt;/span>executionVertexId&lt;span style="color:#f92672">)&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">.&lt;/span>withSlotProfile&lt;span style="color:#f92672">(&lt;/span>requiredSlotProfile&lt;span style="color:#f92672">)&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">.&lt;/span>build&lt;span style="color:#f92672">(),&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> allowQueuedScheduling&lt;span style="color:#f92672">)&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e">// 2. 部署任务
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span> slotAllocationFuture&lt;span style="color:#f92672">.&lt;/span>thenCompose &lt;span style="color:#f92672">{&lt;/span> logicalSlot &lt;span style="color:#66d9ef">=&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">val&lt;/span> executionVertex &lt;span style="color:#66d9ef">=&lt;/span> getExecutionVertex&lt;span style="color:#f92672">(&lt;/span>executionVertexId&lt;span style="color:#f92672">)&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">val&lt;/span> deployment &lt;span style="color:#66d9ef">=&lt;/span> executionVertex&lt;span style="color:#f92672">.&lt;/span>getCurrentExecutionAttempt
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> deployTask&lt;span style="color:#f92672">(&lt;/span>deployment&lt;span style="color:#f92672">,&lt;/span> logicalSlot&lt;span style="color:#f92672">)&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">}&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">}&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e">// 部署任务到TaskManager
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span> &lt;span style="color:#66d9ef">private&lt;/span> &lt;span style="color:#66d9ef">def&lt;/span> deployTask&lt;span style="color:#f92672">(&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> execution&lt;span style="color:#66d9ef">:&lt;/span> &lt;span style="color:#66d9ef">Execution&lt;/span>&lt;span style="color:#f92672">,&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> logicalSlot&lt;span style="color:#66d9ef">:&lt;/span> &lt;span style="color:#66d9ef">LogicalSlot&lt;/span>&lt;span style="color:#f92672">)&lt;/span>&lt;span style="color:#66d9ef">:&lt;/span> &lt;span style="color:#66d9ef">CompletableFuture&lt;/span>&lt;span style="color:#f92672">[&lt;/span>&lt;span style="color:#66d9ef">Void&lt;/span>&lt;span style="color:#f92672">]&lt;/span> &lt;span style="color:#66d9ef">=&lt;/span> &lt;span style="color:#f92672">{&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">try&lt;/span> &lt;span style="color:#f92672">{&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e">// 1. 创建任务部署描述符
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span> &lt;span style="color:#66d9ef">val&lt;/span> taskDeploymentDescriptor &lt;span style="color:#66d9ef">=&lt;/span> createTaskDeploymentDescriptor&lt;span style="color:#f92672">(&lt;/span>execution&lt;span style="color:#f92672">,&lt;/span> logicalSlot&lt;span style="color:#f92672">)&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e">// 2. 获取TaskManager网关
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span> &lt;span style="color:#66d9ef">val&lt;/span> taskManagerGateway &lt;span style="color:#66d9ef">=&lt;/span> logicalSlot&lt;span style="color:#f92672">.&lt;/span>getTaskManagerGateway
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e">// 3. 提交任务到TaskManager
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span> &lt;span style="color:#66d9ef">val&lt;/span> deploymentFuture &lt;span style="color:#66d9ef">=&lt;/span> taskManagerGateway&lt;span style="color:#f92672">.&lt;/span>submitTask&lt;span style="color:#f92672">(&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> taskDeploymentDescriptor&lt;span style="color:#f92672">,&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> jobMasterConfiguration&lt;span style="color:#f92672">,&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> rpcTimeout&lt;span style="color:#f92672">)&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e">// 4. 处理部署结果
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span> deploymentFuture&lt;span style="color:#f92672">.&lt;/span>whenComplete &lt;span style="color:#f92672">{&lt;/span> &lt;span style="color:#f92672">(&lt;/span>&lt;span style="color:#66d9ef">_&lt;/span>&lt;span style="color:#f92672">,&lt;/span> throwable&lt;span style="color:#f92672">)&lt;/span> &lt;span style="color:#66d9ef">=&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">if&lt;/span> &lt;span style="color:#f92672">(&lt;/span>throwable &lt;span style="color:#f92672">!=&lt;/span> &lt;span style="color:#66d9ef">null&lt;/span>&lt;span style="color:#f92672">)&lt;/span> &lt;span style="color:#f92672">{&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> execution&lt;span style="color:#f92672">.&lt;/span>markFailed&lt;span style="color:#f92672">(&lt;/span>throwable&lt;span style="color:#f92672">)&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> freeSlot&lt;span style="color:#f92672">(&lt;/span>logicalSlot&lt;span style="color:#f92672">)&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">}&lt;/span> &lt;span style="color:#66d9ef">else&lt;/span> &lt;span style="color:#f92672">{&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> execution&lt;span style="color:#f92672">.&lt;/span>markDeployed&lt;span style="color:#f92672">()&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">}&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">}&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> deploymentFuture&lt;span style="color:#f92672">.&lt;/span>thenApply&lt;span style="color:#f92672">(&lt;/span>&lt;span style="color:#66d9ef">_&lt;/span> &lt;span style="color:#66d9ef">=&amp;gt;&lt;/span> &lt;span style="color:#66d9ef">null&lt;/span>&lt;span style="color:#66d9ef">:&lt;/span> &lt;span style="color:#66d9ef">Void&lt;/span>&lt;span style="color:#f92672">)&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">}&lt;/span> &lt;span style="color:#66d9ef">catch&lt;/span> &lt;span style="color:#f92672">{&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">case&lt;/span> e&lt;span style="color:#66d9ef">:&lt;/span> &lt;span style="color:#66d9ef">Exception&lt;/span> &lt;span style="color:#f92672">=&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> log&lt;span style="color:#f92672">.&lt;/span>error&lt;span style="color:#f92672">(&lt;/span>&lt;span style="color:#e6db74">s&amp;#34;Failed to deploy task &lt;/span>&lt;span style="color:#e6db74">${&lt;/span>execution&lt;span style="color:#f92672">.&lt;/span>getAttemptId&lt;span style="color:#e6db74">}&lt;/span>&lt;span style="color:#e6db74">&amp;#34;&lt;/span>&lt;span style="color:#f92672">,&lt;/span> e&lt;span style="color:#f92672">)&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> execution&lt;span style="color:#f92672">.&lt;/span>markFailed&lt;span style="color:#f92672">(&lt;/span>e&lt;span style="color:#f92672">)&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> freeSlot&lt;span style="color:#f92672">(&lt;/span>logicalSlot&lt;span style="color:#f92672">)&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">FutureUtils&lt;/span>&lt;span style="color:#f92672">.&lt;/span>completedExceptionally&lt;span style="color:#f92672">[&lt;/span>&lt;span style="color:#66d9ef">Void&lt;/span>&lt;span style="color:#f92672">](&lt;/span>e&lt;span style="color:#f92672">)&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">}&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">}&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e">// 创建任务部署描述符
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span> &lt;span style="color:#66d9ef">private&lt;/span> &lt;span style="color:#66d9ef">def&lt;/span> createTaskDeploymentDescriptor&lt;span style="color:#f92672">(&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> execution&lt;span style="color:#66d9ef">:&lt;/span> &lt;span style="color:#66d9ef">Execution&lt;/span>&lt;span style="color:#f92672">,&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> logicalSlot&lt;span style="color:#66d9ef">:&lt;/span> &lt;span style="color:#66d9ef">LogicalSlot&lt;/span>&lt;span style="color:#f92672">)&lt;/span>&lt;span style="color:#66d9ef">:&lt;/span> &lt;span style="color:#66d9ef">TaskDeploymentDescriptor&lt;/span> &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#f92672">{&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">val&lt;/span> executionVertex &lt;span style="color:#66d9ef">=&lt;/span> execution&lt;span style="color:#f92672">.&lt;/span>getVertex
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">val&lt;/span> executionJobVertex &lt;span style="color:#66d9ef">=&lt;/span> executionVertex&lt;span style="color:#f92672">.&lt;/span>getJobVertex
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">val&lt;/span> jobVertexId &lt;span style="color:#66d9ef">=&lt;/span> executionJobVertex&lt;span style="color:#f92672">.&lt;/span>getJobVertexId
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e">// 1. 获取任务配置
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span> &lt;span style="color:#66d9ef">val&lt;/span> taskConfiguration &lt;span style="color:#66d9ef">=&lt;/span> executionJobVertex&lt;span style="color:#f92672">.&lt;/span>getTaskConfiguration
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e">// 2. 创建输入网关部署描述符
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span> &lt;span style="color:#66d9ef">val&lt;/span> inputGateDeploymentDescriptors &lt;span style="color:#66d9ef">=&lt;/span> createInputGateDeploymentDescriptors&lt;span style="color:#f92672">(&lt;/span>execution&lt;span style="color:#f92672">)&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e">// 3. 创建结果分区部署描述符
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span> &lt;span style="color:#66d9ef">val&lt;/span> resultPartitionDeploymentDescriptors &lt;span style="color:#66d9ef">=&lt;/span> createResultPartitionDeploymentDescriptors&lt;span style="color:#f92672">(&lt;/span>execution&lt;span style="color:#f92672">)&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e">// 4. 构建部署描述符
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span> &lt;span style="color:#66d9ef">new&lt;/span> &lt;span style="color:#a6e22e">TaskDeploymentDescriptor&lt;/span>&lt;span style="color:#f92672">(&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> execution&lt;span style="color:#f92672">.&lt;/span>getAttemptId&lt;span style="color:#f92672">,&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> executionVertex&lt;span style="color:#f92672">.&lt;/span>getTaskNameWithSubtaskIndex&lt;span style="color:#f92672">,&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> jobVertexId&lt;span style="color:#f92672">,&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> execution&lt;span style="color:#f92672">.&lt;/span>getParallelSubtaskIndex&lt;span style="color:#f92672">,&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> execution&lt;span style="color:#f92672">.&lt;/span>getAttemptNumber&lt;span style="color:#f92672">,&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> taskConfiguration&lt;span style="color:#f92672">,&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> executionJobVertex&lt;span style="color:#f92672">.&lt;/span>getJobVertex&lt;span style="color:#f92672">.&lt;/span>getInvokableClassName&lt;span style="color:#f92672">,&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> inputGateDeploymentDescriptors&lt;span style="color:#f92672">,&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> resultPartitionDeploymentDescriptors&lt;span style="color:#f92672">,&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> logicalSlot&lt;span style="color:#f92672">.&lt;/span>getAllocationId&lt;span style="color:#f92672">)&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">}&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e">// 处理任务执行状态更新
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span> &lt;span style="color:#66d9ef">override&lt;/span> &lt;span style="color:#66d9ef">def&lt;/span> updateTaskExecutionState&lt;span style="color:#f92672">(&lt;/span>taskExecutionState&lt;span style="color:#66d9ef">:&lt;/span> &lt;span style="color:#66d9ef">TaskExecutionState&lt;/span>&lt;span style="color:#f92672">)&lt;/span>&lt;span style="color:#66d9ef">:&lt;/span> &lt;span style="color:#66d9ef">Boolean&lt;/span> &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#f92672">{&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">val&lt;/span> executionAttemptID &lt;span style="color:#66d9ef">=&lt;/span> taskExecutionState&lt;span style="color:#f92672">.&lt;/span>getID
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">val&lt;/span> execution &lt;span style="color:#66d9ef">=&lt;/span> executionGraph&lt;span style="color:#f92672">.&lt;/span>getRegisteredExecutions&lt;span style="color:#f92672">.&lt;/span>get&lt;span style="color:#f92672">(&lt;/span>executionAttemptID&lt;span style="color:#f92672">)&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">if&lt;/span> &lt;span style="color:#f92672">(&lt;/span>execution &lt;span style="color:#f92672">!=&lt;/span> &lt;span style="color:#66d9ef">null&lt;/span>&lt;span style="color:#f92672">)&lt;/span> &lt;span style="color:#f92672">{&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">val&lt;/span> executionState &lt;span style="color:#66d9ef">=&lt;/span> taskExecutionState&lt;span style="color:#f92672">.&lt;/span>getExecutionState
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> executionState &lt;span style="color:#66d9ef">match&lt;/span> &lt;span style="color:#f92672">{&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">case&lt;/span> &lt;span style="color:#a6e22e">ExecutionState&lt;/span>&lt;span style="color:#f92672">.&lt;/span>&lt;span style="color:#a6e22e">RUNNING&lt;/span> &lt;span style="color:#66d9ef">=&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> execution&lt;span style="color:#f92672">.&lt;/span>markRunning&lt;span style="color:#f92672">()&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">case&lt;/span> &lt;span style="color:#a6e22e">ExecutionState&lt;/span>&lt;span style="color:#f92672">.&lt;/span>&lt;span style="color:#a6e22e">FINISHED&lt;/span> &lt;span style="color:#66d9ef">=&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> execution&lt;span style="color:#f92672">.&lt;/span>markFinished&lt;span style="color:#f92672">()&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> onTaskFinished&lt;span style="color:#f92672">(&lt;/span>execution&lt;span style="color:#f92672">)&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">case&lt;/span> &lt;span style="color:#a6e22e">ExecutionState&lt;/span>&lt;span style="color:#f92672">.&lt;/span>&lt;span style="color:#a6e22e">FAILED&lt;/span> &lt;span style="color:#66d9ef">=&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">val&lt;/span> cause &lt;span style="color:#66d9ef">=&lt;/span> taskExecutionState&lt;span style="color:#f92672">.&lt;/span>getError&lt;span style="color:#f92672">(&lt;/span>userCodeLoader&lt;span style="color:#f92672">)&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> execution&lt;span style="color:#f92672">.&lt;/span>markFailed&lt;span style="color:#f92672">(&lt;/span>cause&lt;span style="color:#f92672">)&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> executionFailureHandler&lt;span style="color:#f92672">.&lt;/span>handleFailure&lt;span style="color:#f92672">(&lt;/span>execution&lt;span style="color:#f92672">,&lt;/span> cause&lt;span style="color:#f92672">)&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">case&lt;/span> &lt;span style="color:#a6e22e">ExecutionState&lt;/span>&lt;span style="color:#f92672">.&lt;/span>&lt;span style="color:#a6e22e">CANCELED&lt;/span> &lt;span style="color:#66d9ef">=&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> execution&lt;span style="color:#f92672">.&lt;/span>markCanceled&lt;span style="color:#f92672">()&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">case&lt;/span> &lt;span style="color:#66d9ef">_&lt;/span> &lt;span style="color:#66d9ef">=&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> log&lt;span style="color:#f92672">.&lt;/span>warn&lt;span style="color:#f92672">(&lt;/span>&lt;span style="color:#e6db74">s&amp;#34;Unexpected task execution state: &lt;/span>&lt;span style="color:#e6db74">$executionState&lt;/span>&lt;span style="color:#e6db74">&amp;#34;&lt;/span>&lt;span style="color:#f92672">)&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">}&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">true&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">}&lt;/span> &lt;span style="color:#66d9ef">else&lt;/span> &lt;span style="color:#f92672">{&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> log&lt;span style="color:#f92672">.&lt;/span>warn&lt;span style="color:#f92672">(&lt;/span>&lt;span style="color:#e6db74">s&amp;#34;Received state update for unknown execution: &lt;/span>&lt;span style="color:#e6db74">$executionAttemptID&lt;/span>&lt;span style="color:#e6db74">&amp;#34;&lt;/span>&lt;span style="color:#f92672">)&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">false&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">}&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">}&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f92672">}&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h3 id="32-任务部署流程">3.2 任务部署流程&lt;/h3>
&lt;h4 id="flink完整作业执行时序图">Flink完整作业执行时序图&lt;/h4>
&lt;div class="mermaid">sequenceDiagram
participant User as 用户客户端
participant Client as FlinkClient
participant Dispatcher as Dispatcher
participant RM as ResourceManager
participant JM as JobMaster
participant TM1 as TaskManager1
participant TM2 as TaskManager2
participant Task1 as Task实例1
participant Task2 as Task实例2
participant CC as CheckpointCoordinator
Note over User,CC: 1. 作业提交阶段
User->>Client: 提交Flink作业
Client->>Client: 构建StreamGraph
Client->>Client: 生成JobGraph
Client->>Dispatcher: 提交JobGraph
Dispatcher->>JM: 创建JobMaster
JM->>JM: 构建ExecutionGraph
Note over User,CC: 2. 资源申请阶段
JM->>RM: 申请TaskManager资源
RM->>RM: 处理资源请求
RM->>TM1: 启动TaskManager1
RM->>TM2: 启动TaskManager2
TM1->>RM: 注册TaskManager
TM2->>RM: 注册TaskManager
RM-->>JM: 返回可用资源信息
Note over User,CC: 3. Slot分配阶段
JM->>RM: 请求Task Slot
RM->>TM1: 分配Slot1
RM->>TM2: 分配Slot2
TM1-->>RM: 确认Slot1分配
TM2-->>RM: 确认Slot2分配
RM-->>JM: 返回Slot分配结果
Note over User,CC: 4. 任务部署阶段
JM->>JM: 创建TaskDeploymentDescriptor
JM->>TM1: 部署Task1到Slot1
JM->>TM2: 部署Task2到Slot2
TM1->>Task1: 创建Task实例
TM2->>Task2: 创建Task实例
Task1->>TM1: Task初始化完成
Task2->>TM2: Task初始化完成
TM1-->>JM: 部署确认
TM2-->>JM: 部署确认
Note over User,CC: 5. 网络连接建立
JM->>Task1: 建立上下游连接信息
JM->>Task2: 建立上下游连接信息
Task1->>Task2: 建立网络连接
Task2-->>Task1: 连接确认
Note over User,CC: 6. 检查点初始化
JM->>CC: 启动CheckpointCoordinator
CC->>CC: 初始化检查点配置
CC->>Task1: 注册检查点回调
CC->>Task2: 注册检查点回调
Note over User,CC: 7. 任务启动执行
JM->>Task1: 启动Task执行
JM->>Task2: 启动Task执行
Task1->>Task1: 开始处理数据流
Task2->>Task2: 开始处理数据流
Task1->>JM: 报告RUNNING状态
Task2->>JM: 报告RUNNING状态
Note over User,CC: 8. 数据处理阶段
Task1->>Task1: 处理输入数据
Task1->>Task2: 发送处理结果
Task2->>Task2: 接收并处理数据
Task2->>Task2: 输出最终结果
Note over User,CC: 9. 检查点执行
CC->>CC: 触发定期检查点
CC->>Task1: 发起检查点barrier
CC->>Task2: 发起检查点barrier
Task1->>Task1: 保存状态快照
Task2->>Task2: 保存状态快照
Task1-->>CC: 检查点完成确认
Task2-->>CC: 检查点完成确认
CC->>CC: 标记检查点成功
Note over User,CC: 10. 作业监控阶段
Task1->>JM: 定期心跳上报
Task2->>JM: 定期心跳上报
JM->>JM: 监控任务状态
JM->>Client: 上报作业进度
Client-->>User: 显示作业状态
Note over User,CC: 11. 作业完成阶段
Task1->>Task1: 处理完所有数据
Task2->>Task2: 处理完所有数据
Task1->>JM: 报告FINISHED状态
Task2->>JM: 报告FINISHED状态
JM->>JM: 确认作业完成
Note over User,CC: 12. 资源清理阶段
JM->>CC: 停止检查点协调器
JM->>Task1: 停止Task执行
JM->>Task2: 停止Task执行
Task1-->>JM: 确认停止
Task2-->>JM: 确认停止
JM->>RM: 释放Slot资源
RM->>TM1: 释放Slot1
RM->>TM2: 释放Slot2
TM1-->>RM: 资源释放确认
TM2-->>RM: 资源释放确认
JM-->>Dispatcher: 作业执行完成
Dispatcher-->>Client: 返回执行结果
Client-->>User: 作业执行成功
&lt;/div>
&lt;h4 id="详细技术实现时序图">详细技术实现时序图&lt;/h4>
&lt;div class="mermaid">sequenceDiagram
participant User as 用户应用
participant SG as StreamGraph
participant JG as JobGraph
participant EG as ExecutionGraph
participant Scheduler as 调度器
participant SP as SlotProvider
participant RM as ResourceManager
participant TM as TaskManager
participant Task as Task实例
participant OP as Operator
participant State as StateBackend
Note over User,State: Flink作业执行详细时序
rect rgb(240, 248, 255)
Note over User,State: 阶段1: 作业图构建
User->>SG: 创建DataStream程序
SG->>SG: 构建StreamGraph
SG->>JG: 转换为JobGraph
JG->>JG: 优化操作链和资源配置
JG->>EG: 创建ExecutionGraph
EG->>EG: 构建物理执行计划
end
rect rgb(245, 255, 245)
Note over User,State: 阶段2: 调度器初始化
EG->>Scheduler: 创建调度器实例
Scheduler->>SP: 初始化SlotProvider
SP->>RM: 注册到ResourceManager
RM-->>SP: 返回注册确认
Scheduler->>Scheduler: 初始化调度策略
end
rect rgb(255, 248, 240)
Note over User,State: 阶段3: 资源分配与Slot请求
Scheduler->>SP: 请求执行Slot
SP->>RM: 向RM申请资源
RM->>RM: 检查可用资源
RM->>TM: 分配TaskManager资源
TM->>RM: 提供Slot信息
RM->>SP: 返回Slot分配结果
SP-->>Scheduler: Slot分配成功
end
rect rgb(255, 240, 245)
Note over User,State: 阶段4: 任务部署
Scheduler->>Scheduler: 创建TaskDeploymentDescriptor
Scheduler->>TM: 发送任务部署请求
TM->>Task: 创建Task实例
Task->>OP: 初始化Operator链
OP->>State: 初始化状态后端
State-->>OP: 状态后端就绪
OP-->>Task: Operator初始化完成
Task-->>TM: Task创建成功
TM-->>Scheduler: 部署确认
end
rect rgb(248, 240, 255)
Note over User,State: 阶段5: 网络连接建立
Scheduler->>Task: 配置网络连接信息
Task->>Task: 建立InputGate
Task->>Task: 建立ResultPartition
Task->>TM: 网络组件初始化完成
TM->>TM: 建立Task间网络连接
end
rect rgb(240, 255, 240)
Note over User,State: 阶段6: 任务执行
Scheduler->>Task: 启动Task执行
Task->>OP: 调用Operator.open()
OP->>State: 恢复状态数据
State-->>OP: 状态恢复完成
OP->>OP: 开始处理数据元素
OP->>OP: 执行用户定义逻辑
OP->>Task: 处理结果数据
Task->>Scheduler: 报告RUNNING状态
end
rect rgb(255, 255, 240)
Note over User,State: 阶段7: 检查点执行
Scheduler->>Task: 触发检查点
Task->>OP: 发起状态快照
OP->>State: 持久化状态数据
State-->>OP: 快照完成
OP-->>Task: 检查点确认
Task-->>Scheduler: 检查点完成
end
rect rgb(248, 255, 248)
Note over User,State: 阶段8: 任务完成与清理
OP->>OP: 处理完所有数据
OP->>Task: 调用Operator.close()
Task->>Scheduler: 报告FINISHED状态
Scheduler->>SP: 释放Slot资源
SP->>RM: 归还资源到资源池
RM-->>SP: 资源释放确认
Scheduler-->>User: 作业执行完成
end
&lt;/div>
&lt;h4 id="关键时间节点说明">关键时间节点说明&lt;/h4>
&lt;table>
&lt;thead>
&lt;tr>
&lt;th>阶段&lt;/th>
&lt;th>关键操作&lt;/th>
&lt;th>主要组件&lt;/th>
&lt;th>耗时特点&lt;/th>
&lt;/tr>
&lt;/thead>
&lt;tbody>
&lt;tr>
&lt;td>&lt;strong>作业图构建&lt;/strong>&lt;/td>
&lt;td>StreamGraph→JobGraph→ExecutionGraph&lt;/td>
&lt;td>客户端编译&lt;/td>
&lt;td>通常1-3秒&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;strong>调度器初始化&lt;/strong>&lt;/td>
&lt;td>调度器创建、资源发现&lt;/td>
&lt;td>JobMaster&lt;/td>
&lt;td>通常2-5秒&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;strong>资源分配&lt;/strong>&lt;/td>
&lt;td>Slot请求、TaskManager启动&lt;/td>
&lt;td>ResourceManager&lt;/td>
&lt;td>通常5-15秒&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;strong>任务部署&lt;/strong>&lt;/td>
&lt;td>Task创建、Operator初始化&lt;/td>
&lt;td>TaskManager&lt;/td>
&lt;td>通常1-3秒&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;strong>网络建立&lt;/strong>&lt;/td>
&lt;td>InputGate、ResultPartition连接&lt;/td>
&lt;td>网络栈&lt;/td>
&lt;td>通常几百毫秒&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;strong>任务执行&lt;/strong>&lt;/td>
&lt;td>数据流处理、状态计算&lt;/td>
&lt;td>Operator链&lt;/td>
&lt;td>取决于数据量和复杂度&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;strong>检查点&lt;/strong>&lt;/td>
&lt;td>状态快照、持久化&lt;/td>
&lt;td>StateBackend&lt;/td>
&lt;td>通常几秒到几分钟&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;strong>资源清理&lt;/strong>&lt;/td>
&lt;td>Slot释放、资源回收&lt;/td>
&lt;td>ResourceManager&lt;/td>
&lt;td>通常1-3秒&lt;/td>
&lt;/tr>
&lt;/tbody>
&lt;/table>
&lt;h4 id="flink-yarn模式完整执行时序图">Flink YARN模式完整执行时序图&lt;/h4>
&lt;div class="mermaid">sequenceDiagram
participant User as 用户
participant FlinkYarnClient as FlinkYarnClient
participant HDFS as HDFS
participant YarnRM as YARN ResourceManager
participant YarnNM1 as YARN NodeManager1
participant YarnNM2 as YARN NodeManager2
participant YarnAM as YARN ApplicationMaster
participant Dispatcher as Dispatcher
participant JM as JobMaster
participant FlinkRM as Flink ResourceManager
participant TM1 as TaskManager1
participant TM2 as TaskManager2
participant Task1 as Task实例1
participant Task2 as Task实例2
Note over User,Task2: 1. YARN应用提交阶段
User->>FlinkYarnClient: 提交Flink作业到YARN
FlinkYarnClient->>FlinkYarnClient: 准备作业JAR和配置
FlinkYarnClient->>HDFS: 上传Flink应用文件
HDFS-->>FlinkYarnClient: 上传完成
FlinkYarnClient->>YarnRM: 提交ApplicationMaster请求
YarnRM-->>FlinkYarnClient: 返回ApplicationId
Note over User,Task2: 2. ApplicationMaster启动阶段
YarnRM->>YarnRM: 调度AM Container
YarnRM->>YarnNM1: 分配AM Container
YarnNM1->>HDFS: 下载Flink应用文件
HDFS-->>YarnNM1: 返回文件
YarnNM1->>YarnAM: 启动ApplicationMaster
YarnAM->>YarnRM: 向YARN RM注册AM
YarnRM-->>YarnAM: 注册成功
Note over User,Task2: 3. Flink集群初始化阶段
YarnAM->>Dispatcher: 启动Flink Dispatcher
YarnAM->>FlinkRM: 启动Flink ResourceManager
FlinkRM->>YarnRM: 注册为YARN资源请求者
Dispatcher->>Dispatcher: 初始化作业分发服务
FlinkRM->>FlinkRM: 初始化Slot管理器
Note over User,Task2: 4. 作业提交与JobMaster创建
FlinkYarnClient->>Dispatcher: 提交JobGraph
Dispatcher->>JM: 创建JobMaster实例
JM->>JM: 构建ExecutionGraph
JM->>FlinkRM: 注册JobMaster
FlinkRM-->>JM: 注册确认
Note over User,Task2: 5. TaskManager资源申请
JM->>FlinkRM: 请求TaskManager资源
FlinkRM->>YarnRM: 向YARN申请Container
YarnRM->>YarnRM: 调度Container资源
YarnRM->>YarnNM1: 分配Container给TM1
YarnRM->>YarnNM2: 分配Container给TM2
YarnRM-->>FlinkRM: 返回Container分配信息
Note over User,Task2: 6. TaskManager启动阶段
FlinkRM->>YarnNM1: 启动TaskManager1
FlinkRM->>YarnNM2: 启动TaskManager2
YarnNM1->>HDFS: 下载Flink运行时文件
YarnNM2->>HDFS: 下载Flink运行时文件
HDFS-->>YarnNM1: 返回文件
HDFS-->>YarnNM2: 返回文件
YarnNM1->>TM1: 启动TaskManager进程
YarnNM2->>TM2: 启动TaskManager进程
Note over User,Task2: 7. TaskManager注册与Slot提供
TM1->>FlinkRM: 注册TaskManager1
TM2->>FlinkRM: 注册TaskManager2
FlinkRM-->>TM1: 注册确认
FlinkRM-->>TM2: 注册确认
TM1->>FlinkRM: 提供可用Slot
TM2->>FlinkRM: 提供可用Slot
FlinkRM->>JM: 通知Slot可用
Note over User,Task2: 8. 任务部署与执行
JM->>FlinkRM: 请求分配Slot
FlinkRM->>TM1: 分配Slot给Task1
FlinkRM->>TM2: 分配Slot给Task2
JM->>TM1: 部署Task1到Slot
JM->>TM2: 部署Task2到Slot
TM1->>Task1: 创建Task实例
TM2->>Task2: 创建Task实例
Task1-->>TM1: Task初始化完成
Task2-->>TM2: Task初始化完成
TM1-->>JM: Task1部署成功
TM2-->>JM: Task2部署成功
Note over User,Task2: 9. 网络连接与数据处理
JM->>Task1: 启动Task执行
JM->>Task2: 启动Task执行
Task1->>Task2: 建立数据传输连接
Task1->>Task1: 处理输入数据
Task1->>Task2: 发送处理结果
Task2->>Task2: 处理接收数据
Task1->>JM: 报告RUNNING状态
Task2->>JM: 报告RUNNING状态
Note over User,Task2: 10. 检查点与状态管理
JM->>Task1: 触发检查点
JM->>Task2: 触发检查点
Task1->>HDFS: 保存状态快照
Task2->>HDFS: 保存状态快照
HDFS-->>Task1: 快照保存完成
HDFS-->>Task2: 快照保存完成
Task1-->>JM: 检查点完成
Task2-->>JM: 检查点完成
JM->>JM: 标记检查点成功
Note over User,Task2: 11. 作业完成与监控
Task1->>Task1: 处理完所有数据
Task2->>Task2: 处理完所有数据
Task1->>JM: 报告FINISHED状态
Task2->>JM: 报告FINISHED状态
JM->>JM: 确认作业完成
JM-->>Dispatcher: 作业执行结果
Dispatcher-->>FlinkYarnClient: 返回执行结果
Note over User,Task2: 12. 资源清理与释放
JM->>TM1: 停止Task1
JM->>TM2: 停止Task2
Task1-->>TM1: Task停止确认
Task2-->>TM2: Task停止确认
FlinkRM->>YarnRM: 释放Container资源
YarnRM->>YarnNM1: 停止TM1 Container
YarnRM->>YarnNM2: 停止TM2 Container
YarnNM1-->>YarnRM: Container1释放确认
YarnNM2-->>YarnRM: Container2释放确认
YarnAM->>YarnRM: 注销ApplicationMaster
YarnRM-->>YarnAM: 注销成功
YarnRM->>YarnNM1: 停止AM Container
FlinkYarnClient-->>User: Flink作业执行完成
&lt;/div>
&lt;h4 id="flink与spark-yarn模式对比">Flink与Spark YARN模式对比&lt;/h4>
&lt;table>
&lt;thead>
&lt;tr>
&lt;th>对比维度&lt;/th>
&lt;th>Flink YARN模式&lt;/th>
&lt;th>Spark YARN模式&lt;/th>
&lt;/tr>
&lt;/thead>
&lt;tbody>
&lt;tr>
&lt;td>&lt;strong>ApplicationMaster&lt;/strong>&lt;/td>
&lt;td>包含Dispatcher+ResourceManager&lt;/td>
&lt;td>包含Driver(cluster模式)或只是资源协调器&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;strong>作业提交&lt;/strong>&lt;/td>
&lt;td>提交到Dispatcher&lt;/td>
&lt;td>提交到SparkContext&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;strong>资源管理&lt;/strong>&lt;/td>
&lt;td>Flink ResourceManager + YARN RM&lt;/td>
&lt;td>ApplicationMaster + YARN RM&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;strong>任务调度&lt;/strong>&lt;/td>
&lt;td>JobMaster负责单作业调度&lt;/td>
&lt;td>TaskScheduler负责任务调度&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;strong>Slot管理&lt;/strong>&lt;/td>
&lt;td>基于Slot的细粒度资源分配&lt;/td>
&lt;td>基于Executor的粗粒度资源分配&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;strong>容错机制&lt;/strong>&lt;/td>
&lt;td>检查点+任务重启&lt;/td>
&lt;td>RDD血统+Stage重试&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;strong>状态管理&lt;/strong>&lt;/td>
&lt;td>内置状态后端&lt;/td>
&lt;td>依赖外部存储或内存&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;strong>动态资源&lt;/strong>&lt;/td>
&lt;td>Slot级别的动态申请释放&lt;/td>
&lt;td>Executor级别的动态扩缩容&lt;/td>
&lt;/tr>
&lt;/tbody>
&lt;/table>
&lt;h3 id="33-资源分配机制">3.3 资源分配机制&lt;/h3>
&lt;h4 id="slot分配流程图">Slot分配流程图&lt;/h4>
&lt;div class="mermaid">graph TD
A[任务请求Slot] --> B[SlotManager处理请求]
B --> C{是否有可用Slot}
C -->|有| D[分配现有Slot]
C -->|无| E[请求新TaskManager]
D --> F[创建LogicalSlot]
E --> G[ResourceManager分配资源]
G --> H[启动新TaskManager]
H --> I[TaskManager注册Slot]
I --> F
F --> J[连接网络通道]
J --> K[Slot分配成功]
style A fill:#e1f5fe
style E fill:#fff3e0
style K fill:#e8f5e8
&lt;/div>
&lt;hr>
&lt;h2 id="六检查点机制-1">六、检查点机制&lt;/h2>
&lt;h3 id="61-检查点协调器">6.1 检查点协调器&lt;/h3>
&lt;h4 id="检查点触发流程图">检查点触发流程图&lt;/h4>
&lt;div class="mermaid">graph TD
A[CheckpointCoordinator定时触发] --> B[创建PendingCheckpoint]
B --> C[向Source发送CheckpointBarrier]
C --> D[Source接收Barrier并快照状态]
D --> E[向下游发送Barrier]
E --> F[下游算子对齐Barrier]
F --> G[执行状态快照]
G --> H[状态写入StateBackend]
H --> I[向Coordinator确认完成]
I --> J[所有Task确认后完成检查点]
F --> F1[等待所有输入Barrier]
F1 --> F2[缓存后续数据]
F2 --> G
style A fill:#e1f5fe
style F1 fill:#fff3e0
style J fill:#e8f5e8
&lt;/div>
&lt;h4 id="checkpointcoordinator核心源码">CheckpointCoordinator核心源码&lt;/h4>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-scala" data-lang="scala">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">// CheckpointCoordinator.scala - 检查点协调器
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>&lt;span style="color:#66d9ef">class&lt;/span> &lt;span style="color:#a6e22e">CheckpointCoordinator&lt;/span>&lt;span style="color:#f92672">(&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> jobId&lt;span style="color:#66d9ef">:&lt;/span> &lt;span style="color:#66d9ef">JobID&lt;/span>&lt;span style="color:#f92672">,&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> checkpointConfig&lt;span style="color:#66d9ef">:&lt;/span> &lt;span style="color:#66d9ef">CheckpointConfig&lt;/span>&lt;span style="color:#f92672">,&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> executionGraph&lt;span style="color:#66d9ef">:&lt;/span> &lt;span style="color:#66d9ef">ExecutionGraph&lt;/span>&lt;span style="color:#f92672">,&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> checkpointIDCounter&lt;span style="color:#66d9ef">:&lt;/span> &lt;span style="color:#66d9ef">CheckpointIDCounter&lt;/span>&lt;span style="color:#f92672">,&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> completedCheckpointStore&lt;span style="color:#66d9ef">:&lt;/span> &lt;span style="color:#66d9ef">CompletedCheckpointStore&lt;/span>&lt;span style="color:#f92672">,&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> checkpointStorage&lt;span style="color:#66d9ef">:&lt;/span> &lt;span style="color:#66d9ef">CheckpointStorage&lt;/span>&lt;span style="color:#f92672">,&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> ioExecutor&lt;span style="color:#66d9ef">:&lt;/span> &lt;span style="color:#66d9ef">Executor&lt;/span>&lt;span style="color:#f92672">,&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> sharedStateRegistryFactory&lt;span style="color:#66d9ef">:&lt;/span> &lt;span style="color:#66d9ef">SharedStateRegistryFactory&lt;/span>&lt;span style="color:#f92672">,&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> failureManager&lt;span style="color:#66d9ef">:&lt;/span> &lt;span style="color:#66d9ef">CheckpointFailureManager&lt;/span>&lt;span style="color:#f92672">)&lt;/span> &lt;span style="color:#f92672">{&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e">// 待完成的检查点
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span> &lt;span style="color:#66d9ef">private&lt;/span> &lt;span style="color:#66d9ef">val&lt;/span> pendingCheckpoints &lt;span style="color:#66d9ef">=&lt;/span> &lt;span style="color:#66d9ef">new&lt;/span> &lt;span style="color:#a6e22e">ConcurrentHashMap&lt;/span>&lt;span style="color:#f92672">[&lt;/span>&lt;span style="color:#66d9ef">Long&lt;/span>, &lt;span style="color:#66d9ef">PendingCheckpoint&lt;/span>&lt;span style="color:#f92672">]()&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e">// 检查点统计信息
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span> &lt;span style="color:#66d9ef">private&lt;/span> &lt;span style="color:#66d9ef">val&lt;/span> checkpointStatsTracker &lt;span style="color:#66d9ef">=&lt;/span> &lt;span style="color:#66d9ef">new&lt;/span> &lt;span style="color:#a6e22e">CheckpointStatsTracker&lt;/span>&lt;span style="color:#f92672">()&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e">// 定时器服务
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span> &lt;span style="color:#66d9ef">private&lt;/span> &lt;span style="color:#66d9ef">val&lt;/span> timer &lt;span style="color:#66d9ef">=&lt;/span> &lt;span style="color:#66d9ef">new&lt;/span> &lt;span style="color:#a6e22e">Timer&lt;/span>&lt;span style="color:#f92672">(&lt;/span>&lt;span style="color:#e6db74">&amp;#34;Checkpoint Timer&amp;#34;&lt;/span>&lt;span style="color:#f92672">)&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e">// 启动检查点协调器
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span> &lt;span style="color:#66d9ef">def&lt;/span> startCheckpointScheduler&lt;span style="color:#f92672">()&lt;/span>&lt;span style="color:#66d9ef">:&lt;/span> &lt;span style="color:#66d9ef">Unit&lt;/span> &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#f92672">{&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">if&lt;/span> &lt;span style="color:#f92672">(&lt;/span>checkpointConfig&lt;span style="color:#f92672">.&lt;/span>isCheckpointingEnabled&lt;span style="color:#f92672">)&lt;/span> &lt;span style="color:#f92672">{&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">val&lt;/span> baseInterval &lt;span style="color:#66d9ef">=&lt;/span> checkpointConfig&lt;span style="color:#f92672">.&lt;/span>getCheckpointInterval
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">val&lt;/span> randomDelay &lt;span style="color:#66d9ef">=&lt;/span> &lt;span style="color:#a6e22e">ThreadLocalRandom&lt;/span>&lt;span style="color:#f92672">.&lt;/span>current&lt;span style="color:#f92672">().&lt;/span>nextLong&lt;span style="color:#f92672">(&lt;/span>baseInterval&lt;span style="color:#f92672">)&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> timer&lt;span style="color:#f92672">.&lt;/span>schedule&lt;span style="color:#f92672">(&lt;/span>&lt;span style="color:#66d9ef">new&lt;/span> &lt;span style="color:#a6e22e">CheckpointTriggerTask&lt;/span>&lt;span style="color:#f92672">(),&lt;/span> randomDelay&lt;span style="color:#f92672">,&lt;/span> baseInterval&lt;span style="color:#f92672">)&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> logInfo&lt;span style="color:#f92672">(&lt;/span>&lt;span style="color:#e6db74">&amp;#34;Started checkpoint scheduler with interval {} ms&amp;#34;&lt;/span>&lt;span style="color:#f92672">,&lt;/span> baseInterval&lt;span style="color:#f92672">)&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">}&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">}&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e">// 触发检查点的定时任务
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span> &lt;span style="color:#66d9ef">private&lt;/span> &lt;span style="color:#66d9ef">class&lt;/span> &lt;span style="color:#a6e22e">CheckpointTriggerTask&lt;/span> &lt;span style="color:#66d9ef">extends&lt;/span> &lt;span style="color:#a6e22e">TimerTask&lt;/span> &lt;span style="color:#f92672">{&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">override&lt;/span> &lt;span style="color:#66d9ef">def&lt;/span> run&lt;span style="color:#f92672">()&lt;/span>&lt;span style="color:#66d9ef">:&lt;/span> &lt;span style="color:#66d9ef">Unit&lt;/span> &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#f92672">{&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">try&lt;/span> &lt;span style="color:#f92672">{&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> triggerCheckpoint&lt;span style="color:#f92672">(&lt;/span>&lt;span style="color:#a6e22e">CheckpointTriggerRequest&lt;/span>&lt;span style="color:#f92672">.&lt;/span>periodic&lt;span style="color:#f92672">())&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">}&lt;/span> &lt;span style="color:#66d9ef">catch&lt;/span> &lt;span style="color:#f92672">{&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">case&lt;/span> e&lt;span style="color:#66d9ef">:&lt;/span> &lt;span style="color:#66d9ef">Exception&lt;/span> &lt;span style="color:#f92672">=&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> logError&lt;span style="color:#f92672">(&lt;/span>&lt;span style="color:#e6db74">&amp;#34;Failed to trigger checkpoint&amp;#34;&lt;/span>&lt;span style="color:#f92672">,&lt;/span> e&lt;span style="color:#f92672">)&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">}&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">}&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">}&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e">// 触发检查点的核心方法
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span> &lt;span style="color:#66d9ef">def&lt;/span> triggerCheckpoint&lt;span style="color:#f92672">(&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> request&lt;span style="color:#66d9ef">:&lt;/span> &lt;span style="color:#66d9ef">CheckpointTriggerRequest&lt;/span>&lt;span style="color:#f92672">)&lt;/span>&lt;span style="color:#66d9ef">:&lt;/span> &lt;span style="color:#66d9ef">CompletableFuture&lt;/span>&lt;span style="color:#f92672">[&lt;/span>&lt;span style="color:#66d9ef">CompletedCheckpoint&lt;/span>&lt;span style="color:#f92672">]&lt;/span> &lt;span style="color:#66d9ef">=&lt;/span> &lt;span style="color:#f92672">{&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e">// 1. 检查是否可以触发检查点
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span> &lt;span style="color:#66d9ef">val&lt;/span> checkResult &lt;span style="color:#66d9ef">=&lt;/span> isTriggerable&lt;span style="color:#f92672">(&lt;/span>request&lt;span style="color:#f92672">)&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">if&lt;/span> &lt;span style="color:#f92672">(!&lt;/span>checkResult&lt;span style="color:#f92672">.&lt;/span>isTriggerable&lt;span style="color:#f92672">)&lt;/span> &lt;span style="color:#f92672">{&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">return&lt;/span> &lt;span style="color:#a6e22e">FutureUtils&lt;/span>&lt;span style="color:#f92672">.&lt;/span>completedExceptionally&lt;span style="color:#f92672">(&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">new&lt;/span> &lt;span style="color:#a6e22e">CheckpointException&lt;/span>&lt;span style="color:#f92672">(&lt;/span>checkResult&lt;span style="color:#f92672">.&lt;/span>reason&lt;span style="color:#f92672">))&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">}&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e">// 2. 生成检查点ID
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span> &lt;span style="color:#66d9ef">val&lt;/span> checkpointId &lt;span style="color:#66d9ef">=&lt;/span> checkpointIDCounter&lt;span style="color:#f92672">.&lt;/span>getAndIncrement&lt;span style="color:#f92672">()&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">val&lt;/span> timestamp &lt;span style="color:#66d9ef">=&lt;/span> &lt;span style="color:#a6e22e">System&lt;/span>&lt;span style="color:#f92672">.&lt;/span>currentTimeMillis&lt;span style="color:#f92672">()&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e">// 3. 创建PendingCheckpoint
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span> &lt;span style="color:#66d9ef">val&lt;/span> pendingCheckpoint &lt;span style="color:#66d9ef">=&lt;/span> createPendingCheckpoint&lt;span style="color:#f92672">(&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> checkpointId&lt;span style="color:#f92672">,&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> timestamp&lt;span style="color:#f92672">,&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> request&lt;span style="color:#f92672">.&lt;/span>getCheckpointType&lt;span style="color:#f92672">)&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e">// 4. 存储PendingCheckpoint
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span> pendingCheckpoints&lt;span style="color:#f92672">.&lt;/span>put&lt;span style="color:#f92672">(&lt;/span>checkpointId&lt;span style="color:#f92672">,&lt;/span> pendingCheckpoint&lt;span style="color:#f92672">)&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e">// 5. 向Source节点发送CheckpointBarrier
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span> &lt;span style="color:#66d9ef">val&lt;/span> triggerFuture &lt;span style="color:#66d9ef">=&lt;/span> triggerCheckpointBarriers&lt;span style="color:#f92672">(&lt;/span>pendingCheckpoint&lt;span style="color:#f92672">)&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e">// 6. 处理触发结果
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span> triggerFuture&lt;span style="color:#f92672">.&lt;/span>whenComplete &lt;span style="color:#f92672">{&lt;/span> &lt;span style="color:#f92672">(&lt;/span>&lt;span style="color:#66d9ef">_&lt;/span>&lt;span style="color:#f92672">,&lt;/span> throwable&lt;span style="color:#f92672">)&lt;/span> &lt;span style="color:#66d9ef">=&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">if&lt;/span> &lt;span style="color:#f92672">(&lt;/span>throwable &lt;span style="color:#f92672">!=&lt;/span> &lt;span style="color:#66d9ef">null&lt;/span>&lt;span style="color:#f92672">)&lt;/span> &lt;span style="color:#f92672">{&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> logError&lt;span style="color:#f92672">(&lt;/span>&lt;span style="color:#e6db74">s&amp;#34;Failed to trigger checkpoint &lt;/span>&lt;span style="color:#e6db74">$checkpointId&lt;/span>&lt;span style="color:#e6db74">&amp;#34;&lt;/span>&lt;span style="color:#f92672">,&lt;/span> throwable&lt;span style="color:#f92672">)&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> discardPendingCheckpoint&lt;span style="color:#f92672">(&lt;/span>pendingCheckpoint&lt;span style="color:#f92672">,&lt;/span> throwable&lt;span style="color:#f92672">)&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">}&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">}&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> pendingCheckpoint&lt;span style="color:#f92672">.&lt;/span>getCompletionFuture
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">}&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e">// 创建PendingCheckpoint
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span> &lt;span style="color:#66d9ef">private&lt;/span> &lt;span style="color:#66d9ef">def&lt;/span> createPendingCheckpoint&lt;span style="color:#f92672">(&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> checkpointId&lt;span style="color:#66d9ef">:&lt;/span> &lt;span style="color:#66d9ef">Long&lt;/span>&lt;span style="color:#f92672">,&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> timestamp&lt;span style="color:#66d9ef">:&lt;/span> &lt;span style="color:#66d9ef">Long&lt;/span>&lt;span style="color:#f92672">,&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> checkpointType&lt;span style="color:#66d9ef">:&lt;/span> &lt;span style="color:#66d9ef">CheckpointType&lt;/span>&lt;span style="color:#f92672">)&lt;/span>&lt;span style="color:#66d9ef">:&lt;/span> &lt;span style="color:#66d9ef">PendingCheckpoint&lt;/span> &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#f92672">{&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e">// 1. 获取需要确认的ExecutionVertex
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span> &lt;span style="color:#66d9ef">val&lt;/span> tasksToWaitFor &lt;span style="color:#66d9ef">=&lt;/span> &lt;span style="color:#66d9ef">new&lt;/span> util&lt;span style="color:#f92672">.&lt;/span>&lt;span style="color:#a6e22e">ArrayList&lt;/span>&lt;span style="color:#f92672">[&lt;/span>&lt;span style="color:#66d9ef">ExecutionVertex&lt;/span>&lt;span style="color:#f92672">]()&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">for&lt;/span> &lt;span style="color:#f92672">(&lt;/span>jobVertex &lt;span style="color:#66d9ef">&amp;lt;-&lt;/span> executionGraph&lt;span style="color:#f92672">.&lt;/span>getVerticesTopologically&lt;span style="color:#f92672">.&lt;/span>asScala&lt;span style="color:#f92672">)&lt;/span> &lt;span style="color:#f92672">{&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">for&lt;/span> &lt;span style="color:#f92672">(&lt;/span>executionVertex &lt;span style="color:#66d9ef">&amp;lt;-&lt;/span> jobVertex&lt;span style="color:#f92672">.&lt;/span>getTaskVertices&lt;span style="color:#f92672">)&lt;/span> &lt;span style="color:#f92672">{&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">if&lt;/span> &lt;span style="color:#f92672">(&lt;/span>executionVertex&lt;span style="color:#f92672">.&lt;/span>getExecutionState &lt;span style="color:#f92672">==&lt;/span> &lt;span style="color:#a6e22e">ExecutionState&lt;/span>&lt;span style="color:#f92672">.&lt;/span>&lt;span style="color:#a6e22e">RUNNING&lt;/span>&lt;span style="color:#f92672">)&lt;/span> &lt;span style="color:#f92672">{&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> tasksToWaitFor&lt;span style="color:#f92672">.&lt;/span>add&lt;span style="color:#f92672">(&lt;/span>executionVertex&lt;span style="color:#f92672">)&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">}&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">}&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">}&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e">// 2. 创建检查点存储位置
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span> &lt;span style="color:#66d9ef">val&lt;/span> checkpointStorageLocation &lt;span style="color:#66d9ef">=&lt;/span> checkpointStorage&lt;span style="color:#f92672">.&lt;/span>initializeLocationForCheckpoint&lt;span style="color:#f92672">(&lt;/span>checkpointId&lt;span style="color:#f92672">)&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e">// 3. 创建PendingCheckpoint
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span> &lt;span style="color:#66d9ef">new&lt;/span> &lt;span style="color:#a6e22e">PendingCheckpoint&lt;/span>&lt;span style="color:#f92672">(&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> jobId&lt;span style="color:#f92672">,&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> checkpointId&lt;span style="color:#f92672">,&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> timestamp&lt;span style="color:#f92672">,&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> tasksToWaitFor&lt;span style="color:#f92672">,&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> checkpointConfig&lt;span style="color:#f92672">.&lt;/span>getMaxConcurrentCheckpoints&lt;span style="color:#f92672">,&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> checkpointConfig&lt;span style="color:#f92672">.&lt;/span>getCheckpointTimeout&lt;span style="color:#f92672">,&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> checkpointStorageLocation&lt;span style="color:#f92672">,&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> ioExecutor&lt;span style="color:#f92672">,&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> sharedStateRegistryFactory&lt;span style="color:#f92672">.&lt;/span>create&lt;span style="color:#f92672">(&lt;/span>ioExecutor&lt;span style="color:#f92672">))&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">}&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e">// 向Source节点发送CheckpointBarrier
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span> &lt;span style="color:#66d9ef">private&lt;/span> &lt;span style="color:#66d9ef">def&lt;/span> triggerCheckpointBarriers&lt;span style="color:#f92672">(&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> pendingCheckpoint&lt;span style="color:#66d9ef">:&lt;/span> &lt;span style="color:#66d9ef">PendingCheckpoint&lt;/span>&lt;span style="color:#f92672">)&lt;/span>&lt;span style="color:#66d9ef">:&lt;/span> &lt;span style="color:#66d9ef">CompletableFuture&lt;/span>&lt;span style="color:#f92672">[&lt;/span>&lt;span style="color:#66d9ef">Void&lt;/span>&lt;span style="color:#f92672">]&lt;/span> &lt;span style="color:#66d9ef">=&lt;/span> &lt;span style="color:#f92672">{&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">val&lt;/span> checkpointId &lt;span style="color:#66d9ef">=&lt;/span> pendingCheckpoint&lt;span style="color:#f92672">.&lt;/span>getCheckpointId
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">val&lt;/span> timestamp &lt;span style="color:#66d9ef">=&lt;/span> pendingCheckpoint&lt;span style="color:#f92672">.&lt;/span>getCheckpointTimestamp
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e">// 1. 获取所有Source节点
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span> &lt;span style="color:#66d9ef">val&lt;/span> sourceExecutions &lt;span style="color:#66d9ef">=&lt;/span> &lt;span style="color:#66d9ef">new&lt;/span> util&lt;span style="color:#f92672">.&lt;/span>&lt;span style="color:#a6e22e">ArrayList&lt;/span>&lt;span style="color:#f92672">[&lt;/span>&lt;span style="color:#66d9ef">Execution&lt;/span>&lt;span style="color:#f92672">]()&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">for&lt;/span> &lt;span style="color:#f92672">(&lt;/span>jobVertex &lt;span style="color:#66d9ef">&amp;lt;-&lt;/span> executionGraph&lt;span style="color:#f92672">.&lt;/span>getVerticesTopologically&lt;span style="color:#f92672">.&lt;/span>asScala&lt;span style="color:#f92672">)&lt;/span> &lt;span style="color:#f92672">{&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">if&lt;/span> &lt;span style="color:#f92672">(&lt;/span>jobVertex&lt;span style="color:#f92672">.&lt;/span>getJobVertex&lt;span style="color:#f92672">.&lt;/span>isInputVertex&lt;span style="color:#f92672">)&lt;/span> &lt;span style="color:#f92672">{&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">for&lt;/span> &lt;span style="color:#f92672">(&lt;/span>executionVertex &lt;span style="color:#66d9ef">&amp;lt;-&lt;/span> jobVertex&lt;span style="color:#f92672">.&lt;/span>getTaskVertices&lt;span style="color:#f92672">)&lt;/span> &lt;span style="color:#f92672">{&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> sourceExecutions&lt;span style="color:#f92672">.&lt;/span>add&lt;span style="color:#f92672">(&lt;/span>executionVertex&lt;span style="color:#f92672">.&lt;/span>getCurrentExecutionAttempt&lt;span style="color:#f92672">)&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">}&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">}&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">}&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e">// 2. 向Source节点发送TriggerCheckpoint消息
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span> &lt;span style="color:#66d9ef">val&lt;/span> triggerFutures &lt;span style="color:#66d9ef">=&lt;/span> sourceExecutions&lt;span style="color:#f92672">.&lt;/span>asScala&lt;span style="color:#f92672">.&lt;/span>map &lt;span style="color:#f92672">{&lt;/span> execution &lt;span style="color:#66d9ef">=&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">val&lt;/span> checkpointOptions &lt;span style="color:#66d9ef">=&lt;/span> &lt;span style="color:#a6e22e">CheckpointOptions&lt;/span>&lt;span style="color:#f92672">.&lt;/span>forCheckpointWithDefaultLocation&lt;span style="color:#f92672">()&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> execution&lt;span style="color:#f92672">.&lt;/span>triggerCheckpoint&lt;span style="color:#f92672">(&lt;/span>checkpointId&lt;span style="color:#f92672">,&lt;/span> timestamp&lt;span style="color:#f92672">,&lt;/span> checkpointOptions&lt;span style="color:#f92672">)&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">}&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e">// 3. 等待所有Source确认
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span> &lt;span style="color:#a6e22e">CompletableFuture&lt;/span>&lt;span style="color:#f92672">.&lt;/span>allOf&lt;span style="color:#f92672">(&lt;/span>triggerFutures&lt;span style="color:#f92672">.&lt;/span>toArray&lt;span style="color:#66d9ef">:&lt;/span> &lt;span style="color:#66d9ef">_&lt;/span>&lt;span style="color:#66d9ef">*&lt;/span>&lt;span style="color:#f92672">)&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">}&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e">// 接收检查点确认
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span> &lt;span style="color:#66d9ef">def&lt;/span> receiveAcknowledgeMessage&lt;span style="color:#f92672">(&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> message&lt;span style="color:#66d9ef">:&lt;/span> &lt;span style="color:#66d9ef">AcknowledgeCheckpoint&lt;/span>&lt;span style="color:#f92672">,&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> taskManagerLocationInfo&lt;span style="color:#66d9ef">:&lt;/span> &lt;span style="color:#66d9ef">String&lt;/span>&lt;span style="color:#f92672">)&lt;/span>&lt;span style="color:#66d9ef">:&lt;/span> &lt;span style="color:#66d9ef">Boolean&lt;/span> &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#f92672">{&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">val&lt;/span> checkpointId &lt;span style="color:#66d9ef">=&lt;/span> message&lt;span style="color:#f92672">.&lt;/span>getCheckpointId
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">val&lt;/span> pendingCheckpoint &lt;span style="color:#66d9ef">=&lt;/span> pendingCheckpoints&lt;span style="color:#f92672">.&lt;/span>get&lt;span style="color:#f92672">(&lt;/span>checkpointId&lt;span style="color:#f92672">)&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">if&lt;/span> &lt;span style="color:#f92672">(&lt;/span>pendingCheckpoint &lt;span style="color:#f92672">==&lt;/span> &lt;span style="color:#66d9ef">null&lt;/span>&lt;span style="color:#f92672">)&lt;/span> &lt;span style="color:#f92672">{&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> logDebug&lt;span style="color:#f92672">(&lt;/span>&lt;span style="color:#e6db74">s&amp;#34;Received acknowledgment for unknown checkpoint &lt;/span>&lt;span style="color:#e6db74">$checkpointId&lt;/span>&lt;span style="color:#e6db74">&amp;#34;&lt;/span>&lt;span style="color:#f92672">)&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">return&lt;/span> &lt;span style="color:#66d9ef">false&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">}&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e">// 1. 确认任务状态
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span> &lt;span style="color:#66d9ef">val&lt;/span> acknowledgeResult &lt;span style="color:#66d9ef">=&lt;/span> pendingCheckpoint&lt;span style="color:#f92672">.&lt;/span>acknowledgeTask&lt;span style="color:#f92672">(&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> message&lt;span style="color:#f92672">.&lt;/span>getTaskExecutionId&lt;span style="color:#f92672">,&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> message&lt;span style="color:#f92672">.&lt;/span>getSubtaskState&lt;span style="color:#f92672">,&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> message&lt;span style="color:#f92672">.&lt;/span>getCheckpointMetrics&lt;span style="color:#f92672">)&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">if&lt;/span> &lt;span style="color:#f92672">(&lt;/span>acknowledgeResult &lt;span style="color:#f92672">==&lt;/span> &lt;span style="color:#a6e22e">AcknowledgeResult&lt;/span>&lt;span style="color:#f92672">.&lt;/span>&lt;span style="color:#a6e22e">SUCCESS&lt;/span>&lt;span style="color:#f92672">)&lt;/span> &lt;span style="color:#f92672">{&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e">// 2. 检查是否所有任务都已确认
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span> &lt;span style="color:#66d9ef">if&lt;/span> &lt;span style="color:#f92672">(&lt;/span>pendingCheckpoint&lt;span style="color:#f92672">.&lt;/span>areTasksFullyAcknowledged&lt;span style="color:#f92672">)&lt;/span> &lt;span style="color:#f92672">{&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> completePendingCheckpoint&lt;span style="color:#f92672">(&lt;/span>pendingCheckpoint&lt;span style="color:#f92672">)&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">}&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">return&lt;/span> &lt;span style="color:#66d9ef">true&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">}&lt;/span> &lt;span style="color:#66d9ef">else&lt;/span> &lt;span style="color:#f92672">{&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> logWarn&lt;span style="color:#f92672">(&lt;/span>&lt;span style="color:#e6db74">s&amp;#34;Failed to acknowledge checkpoint &lt;/span>&lt;span style="color:#e6db74">$checkpointId&lt;/span>&lt;span style="color:#e6db74">: &lt;/span>&lt;span style="color:#e6db74">$acknowledgeResult&lt;/span>&lt;span style="color:#e6db74">&amp;#34;&lt;/span>&lt;span style="color:#f92672">)&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">return&lt;/span> &lt;span style="color:#66d9ef">false&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">}&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">}&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e">// 完成检查点
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span> &lt;span style="color:#66d9ef">private&lt;/span> &lt;span style="color:#66d9ef">def&lt;/span> completePendingCheckpoint&lt;span style="color:#f92672">(&lt;/span>pendingCheckpoint&lt;span style="color:#66d9ef">:&lt;/span> &lt;span style="color:#66d9ef">PendingCheckpoint&lt;/span>&lt;span style="color:#f92672">)&lt;/span>&lt;span style="color:#66d9ef">:&lt;/span> &lt;span style="color:#66d9ef">Unit&lt;/span> &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#f92672">{&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">val&lt;/span> checkpointId &lt;span style="color:#66d9ef">=&lt;/span> pendingCheckpoint&lt;span style="color:#f92672">.&lt;/span>getCheckpointId
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">try&lt;/span> &lt;span style="color:#f92672">{&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e">// 1. 最终化检查点存储
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span> &lt;span style="color:#66d9ef">val&lt;/span> completedCheckpointStorageLocation &lt;span style="color:#66d9ef">=&lt;/span> pendingCheckpoint&lt;span style="color:#f92672">.&lt;/span>finalizeCheckpointExclusively&lt;span style="color:#f92672">()&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e">// 2. 创建CompletedCheckpoint
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span> &lt;span style="color:#66d9ef">val&lt;/span> completedCheckpoint &lt;span style="color:#66d9ef">=&lt;/span> &lt;span style="color:#66d9ef">new&lt;/span> &lt;span style="color:#a6e22e">CompletedCheckpoint&lt;/span>&lt;span style="color:#f92672">(&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> jobId&lt;span style="color:#f92672">,&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> checkpointId&lt;span style="color:#f92672">,&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> pendingCheckpoint&lt;span style="color:#f92672">.&lt;/span>getCheckpointTimestamp&lt;span style="color:#f92672">,&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">System&lt;/span>&lt;span style="color:#f92672">.&lt;/span>currentTimeMillis&lt;span style="color:#f92672">(),&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> pendingCheckpoint&lt;span style="color:#f92672">.&lt;/span>getTaskStates&lt;span style="color:#f92672">,&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> pendingCheckpoint&lt;span style="color:#f92672">.&lt;/span>getMasterState&lt;span style="color:#f92672">,&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> completedCheckpointStorageLocation&lt;span style="color:#f92672">,&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> pendingCheckpoint&lt;span style="color:#f92672">.&lt;/span>getExternalPointer&lt;span style="color:#f92672">)&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e">// 3. 存储完成的检查点
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span> completedCheckpointStore&lt;span style="color:#f92672">.&lt;/span>addCheckpoint&lt;span style="color:#f92672">(&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> completedCheckpoint&lt;span style="color:#f92672">,&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> checkpointsCleaner&lt;span style="color:#f92672">,&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">()&lt;/span> &lt;span style="color:#66d9ef">=&amp;gt;&lt;/span> pendingCheckpoint&lt;span style="color:#f92672">.&lt;/span>getStatsCallback&lt;span style="color:#f92672">.&lt;/span>reportCompletedCheckpoint&lt;span style="color:#f92672">(&lt;/span>completedCheckpoint&lt;span style="color:#f92672">.&lt;/span>getExternalPointer&lt;span style="color:#f92672">))&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e">// 4. 清理PendingCheckpoint
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span> pendingCheckpoints&lt;span style="color:#f92672">.&lt;/span>remove&lt;span style="color:#f92672">(&lt;/span>checkpointId&lt;span style="color:#f92672">)&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e">// 5. 通知完成
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span> pendingCheckpoint&lt;span style="color:#f92672">.&lt;/span>reportCompletedCheckpoint&lt;span style="color:#f92672">(&lt;/span>completedCheckpoint&lt;span style="color:#f92672">)&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> logInfo&lt;span style="color:#f92672">(&lt;/span>&lt;span style="color:#e6db74">s&amp;#34;Completed checkpoint &lt;/span>&lt;span style="color:#e6db74">$checkpointId&lt;/span>&lt;span style="color:#e6db74">&amp;#34;&lt;/span>&lt;span style="color:#f92672">)&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">}&lt;/span> &lt;span style="color:#66d9ef">catch&lt;/span> &lt;span style="color:#f92672">{&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">case&lt;/span> e&lt;span style="color:#66d9ef">:&lt;/span> &lt;span style="color:#66d9ef">Exception&lt;/span> &lt;span style="color:#f92672">=&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> logError&lt;span style="color:#f92672">(&lt;/span>&lt;span style="color:#e6db74">s&amp;#34;Failed to complete checkpoint &lt;/span>&lt;span style="color:#e6db74">$checkpointId&lt;/span>&lt;span style="color:#e6db74">&amp;#34;&lt;/span>&lt;span style="color:#f92672">,&lt;/span> e&lt;span style="color:#f92672">)&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> discardPendingCheckpoint&lt;span style="color:#f92672">(&lt;/span>pendingCheckpoint&lt;span style="color:#f92672">,&lt;/span> e&lt;span style="color:#f92672">)&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">}&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">}&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e">// 丢弃失败的检查点
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span> &lt;span style="color:#66d9ef">private&lt;/span> &lt;span style="color:#66d9ef">def&lt;/span> discardPendingCheckpoint&lt;span style="color:#f92672">(&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> pendingCheckpoint&lt;span style="color:#66d9ef">:&lt;/span> &lt;span style="color:#66d9ef">PendingCheckpoint&lt;/span>&lt;span style="color:#f92672">,&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> cause&lt;span style="color:#66d9ef">:&lt;/span> &lt;span style="color:#66d9ef">Throwable&lt;/span>&lt;span style="color:#f92672">)&lt;/span>&lt;span style="color:#66d9ef">:&lt;/span> &lt;span style="color:#66d9ef">Unit&lt;/span> &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#f92672">{&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">val&lt;/span> checkpointId &lt;span style="color:#66d9ef">=&lt;/span> pendingCheckpoint&lt;span style="color:#f92672">.&lt;/span>getCheckpointId
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> pendingCheckpoints&lt;span style="color:#f92672">.&lt;/span>remove&lt;span style="color:#f92672">(&lt;/span>checkpointId&lt;span style="color:#f92672">)&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">try&lt;/span> &lt;span style="color:#f92672">{&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> pendingCheckpoint&lt;span style="color:#f92672">.&lt;/span>abort&lt;span style="color:#f92672">(&lt;/span>&lt;span style="color:#a6e22e">CheckpointFailureReason&lt;/span>&lt;span style="color:#f92672">.&lt;/span>&lt;span style="color:#a6e22e">CHECKPOINT_COORDINATOR_SHUTDOWN&lt;/span>&lt;span style="color:#f92672">)&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> failureManager&lt;span style="color:#f92672">.&lt;/span>handleCheckpointFailure&lt;span style="color:#f92672">(&lt;/span>pendingCheckpoint&lt;span style="color:#f92672">,&lt;/span> cause&lt;span style="color:#f92672">)&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">}&lt;/span> &lt;span style="color:#66d9ef">catch&lt;/span> &lt;span style="color:#f92672">{&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">case&lt;/span> e&lt;span style="color:#66d9ef">:&lt;/span> &lt;span style="color:#66d9ef">Exception&lt;/span> &lt;span style="color:#f92672">=&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> logError&lt;span style="color:#f92672">(&lt;/span>&lt;span style="color:#e6db74">s&amp;#34;Failed to discard checkpoint &lt;/span>&lt;span style="color:#e6db74">$checkpointId&lt;/span>&lt;span style="color:#e6db74">&amp;#34;&lt;/span>&lt;span style="color:#f92672">,&lt;/span> e&lt;span style="color:#f92672">)&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">}&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">}&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f92672">}&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h3 id="62-分布式快照算法">6.2 分布式快照算法&lt;/h3>
&lt;h4 id="chandy-lamport算法实现">Chandy-Lamport算法实现&lt;/h4>
&lt;div class="mermaid">graph TD
A[算子接收CheckpointBarrier] --> B{是否为第一个Barrier}
B -->|是| C[开始状态快照]
B -->|否| D[检查Barrier对齐]
C --> E[快照本地状态]
E --> F[向下游发送Barrier]
F --> G[继续处理数据]
D --> H{所有输入Barrier到齐}
H -->|否| I[缓存后续数据]
H -->|是| J[执行状态快照]
I --> H
J --> K[处理缓存数据]
K --> F
style A fill:#e1f5fe
style C fill:#fff3e0
style J fill:#e8f5e8
&lt;/div>
&lt;h4 id="checkpointbarrier处理源码">CheckpointBarrier处理源码&lt;/h4>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-scala" data-lang="scala">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">// CheckpointBarrierHandler.scala - CheckpointBarrier处理器
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>&lt;span style="color:#66d9ef">abstract&lt;/span> &lt;span style="color:#66d9ef">class&lt;/span> &lt;span style="color:#a6e22e">CheckpointBarrierHandler&lt;/span>&lt;span style="color:#f92672">(&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">val&lt;/span> inputGate&lt;span style="color:#66d9ef">:&lt;/span> &lt;span style="color:#66d9ef">IndexedInputGate&lt;/span>&lt;span style="color:#f92672">,&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">val&lt;/span> ioExecutor&lt;span style="color:#66d9ef">:&lt;/span> &lt;span style="color:#66d9ef">Executor&lt;/span>&lt;span style="color:#f92672">)&lt;/span> &lt;span style="color:#f92672">{&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e">// 检查点状态跟踪
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span> &lt;span style="color:#66d9ef">protected&lt;/span> &lt;span style="color:#66d9ef">val&lt;/span> pendingCheckpoints &lt;span style="color:#66d9ef">=&lt;/span> &lt;span style="color:#66d9ef">new&lt;/span> util&lt;span style="color:#f92672">.&lt;/span>&lt;span style="color:#a6e22e">TreeMap&lt;/span>&lt;span style="color:#f92672">[&lt;/span>&lt;span style="color:#66d9ef">Long&lt;/span>, &lt;span style="color:#66d9ef">CheckpointBarrierCount&lt;/span>&lt;span style="color:#f92672">]()&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e">// 处理CheckpointBarrier的核心方法
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span> &lt;span style="color:#66d9ef">def&lt;/span> processBarrier&lt;span style="color:#f92672">(&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> barrier&lt;span style="color:#66d9ef">:&lt;/span> &lt;span style="color:#66d9ef">CheckpointBarrier&lt;/span>&lt;span style="color:#f92672">,&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> channelInfo&lt;span style="color:#66d9ef">:&lt;/span> &lt;span style="color:#66d9ef">InputChannelInfo&lt;/span>&lt;span style="color:#f92672">,&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> bufferReceivedTimestamp&lt;span style="color:#66d9ef">:&lt;/span> &lt;span style="color:#66d9ef">Long&lt;/span>&lt;span style="color:#f92672">)&lt;/span>&lt;span style="color:#66d9ef">:&lt;/span> &lt;span style="color:#66d9ef">Unit&lt;/span> &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#f92672">{&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">val&lt;/span> checkpointId &lt;span style="color:#66d9ef">=&lt;/span> barrier&lt;span style="color:#f92672">.&lt;/span>getId
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">val&lt;/span> checkpoint &lt;span style="color:#66d9ef">=&lt;/span> pendingCheckpoints&lt;span style="color:#f92672">.&lt;/span>computeIfAbsent&lt;span style="color:#f92672">(&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> checkpointId&lt;span style="color:#f92672">,&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">_&lt;/span> &lt;span style="color:#66d9ef">=&amp;gt;&lt;/span> &lt;span style="color:#66d9ef">new&lt;/span> &lt;span style="color:#a6e22e">CheckpointBarrierCount&lt;/span>&lt;span style="color:#f92672">(&lt;/span>inputGate&lt;span style="color:#f92672">.&lt;/span>getNumberOfInputChannels&lt;span style="color:#f92672">))&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e">// 标记通道已接收Barrier
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span> &lt;span style="color:#66d9ef">if&lt;/span> &lt;span style="color:#f92672">(&lt;/span>checkpoint&lt;span style="color:#f92672">.&lt;/span>markChannelBarrierReceived&lt;span style="color:#f92672">(&lt;/span>channelInfo&lt;span style="color:#f92672">.&lt;/span>getInputChannelIdx&lt;span style="color:#f92672">))&lt;/span> &lt;span style="color:#f92672">{&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e">// 如果所有通道的Barrier都已接收
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span> &lt;span style="color:#66d9ef">if&lt;/span> &lt;span style="color:#f92672">(&lt;/span>checkpoint&lt;span style="color:#f92672">.&lt;/span>isFullyReceived&lt;span style="color:#f92672">)&lt;/span> &lt;span style="color:#f92672">{&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e">// 触发检查点
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span> notifyCheckpoint&lt;span style="color:#f92672">(&lt;/span>barrier&lt;span style="color:#f92672">,&lt;/span> bufferReceivedTimestamp&lt;span style="color:#f92672">,&lt;/span> checkpointId&lt;span style="color:#f92672">)&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> pendingCheckpoints&lt;span style="color:#f92672">.&lt;/span>remove&lt;span style="color:#f92672">(&lt;/span>checkpointId&lt;span style="color:#f92672">)&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">}&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">}&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">}&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e">// 通知检查点触发
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span> &lt;span style="color:#66d9ef">protected&lt;/span> &lt;span style="color:#66d9ef">def&lt;/span> notifyCheckpoint&lt;span style="color:#f92672">(&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> barrier&lt;span style="color:#66d9ef">:&lt;/span> &lt;span style="color:#66d9ef">CheckpointBarrier&lt;/span>&lt;span style="color:#f92672">,&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> bufferReceivedTimestamp&lt;span style="color:#66d9ef">:&lt;/span> &lt;span style="color:#66d9ef">Long&lt;/span>&lt;span style="color:#f92672">,&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> checkpointId&lt;span style="color:#66d9ef">:&lt;/span> &lt;span style="color:#66d9ef">Long&lt;/span>&lt;span style="color:#f92672">)&lt;/span>&lt;span style="color:#66d9ef">:&lt;/span> &lt;span style="color:#66d9ef">Unit&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e">// 处理检查点取消
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span> &lt;span style="color:#66d9ef">def&lt;/span> processCancellationBarrier&lt;span style="color:#f92672">(&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> cancelBarrier&lt;span style="color:#66d9ef">:&lt;/span> &lt;span style="color:#66d9ef">CancelCheckpointMarker&lt;/span>&lt;span style="color:#f92672">,&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> channelInfo&lt;span style="color:#66d9ef">:&lt;/span> &lt;span style="color:#66d9ef">InputChannelInfo&lt;/span>&lt;span style="color:#f92672">)&lt;/span>&lt;span style="color:#66d9ef">:&lt;/span> &lt;span style="color:#66d9ef">Unit&lt;/span> &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#f92672">{&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">val&lt;/span> checkpointId &lt;span style="color:#66d9ef">=&lt;/span> cancelBarrier&lt;span style="color:#f92672">.&lt;/span>getCheckpointId
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> pendingCheckpoints&lt;span style="color:#f92672">.&lt;/span>remove&lt;span style="color:#f92672">(&lt;/span>checkpointId&lt;span style="color:#f92672">)&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> notifyAbort&lt;span style="color:#f92672">(&lt;/span>checkpointId&lt;span style="color:#f92672">,&lt;/span> &lt;span style="color:#66d9ef">new&lt;/span> &lt;span style="color:#a6e22e">CheckpointException&lt;/span>&lt;span style="color:#f92672">(&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">CheckpointFailureReason&lt;/span>&lt;span style="color:#f92672">.&lt;/span>&lt;span style="color:#a6e22e">CHECKPOINT_DECLINED_ON_CANCELLATION_BARRIER&lt;/span>&lt;span style="color:#f92672">))&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">}&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">protected&lt;/span> &lt;span style="color:#66d9ef">def&lt;/span> notifyAbort&lt;span style="color:#f92672">(&lt;/span>checkpointId&lt;span style="color:#66d9ef">:&lt;/span> &lt;span style="color:#66d9ef">Long&lt;/span>&lt;span style="color:#f92672">,&lt;/span> cause&lt;span style="color:#66d9ef">:&lt;/span> &lt;span style="color:#66d9ef">CheckpointException&lt;/span>&lt;span style="color:#f92672">)&lt;/span>&lt;span style="color:#66d9ef">:&lt;/span> &lt;span style="color:#66d9ef">Unit&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f92672">}&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">// CheckpointBarrierAligner.scala - 精确一次对齐实现
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>&lt;span style="color:#66d9ef">class&lt;/span> &lt;span style="color:#a6e22e">CheckpointBarrierAligner&lt;/span>&lt;span style="color:#f92672">(&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> inputGate&lt;span style="color:#66d9ef">:&lt;/span> &lt;span style="color:#66d9ef">IndexedInputGate&lt;/span>&lt;span style="color:#f92672">,&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> ioExecutor&lt;span style="color:#66d9ef">:&lt;/span> &lt;span style="color:#66d9ef">Executor&lt;/span>&lt;span style="color:#f92672">,&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> bufferStorage&lt;span style="color:#66d9ef">:&lt;/span> &lt;span style="color:#66d9ef">BufferStorage&lt;/span>&lt;span style="color:#f92672">)&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">extends&lt;/span> &lt;span style="color:#a6e22e">CheckpointBarrierHandler&lt;/span>&lt;span style="color:#f92672">(&lt;/span>inputGate&lt;span style="color:#f92672">,&lt;/span> ioExecutor&lt;span style="color:#f92672">)&lt;/span> &lt;span style="color:#f92672">{&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e">// 阻塞的输入通道
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span> &lt;span style="color:#66d9ef">private&lt;/span> &lt;span style="color:#66d9ef">val&lt;/span> blockedChannels &lt;span style="color:#66d9ef">=&lt;/span> &lt;span style="color:#66d9ef">new&lt;/span> util&lt;span style="color:#f92672">.&lt;/span>&lt;span style="color:#a6e22e">BitSet&lt;/span>&lt;span style="color:#f92672">(&lt;/span>inputGate&lt;span style="color:#f92672">.&lt;/span>getNumberOfInputChannels&lt;span style="color:#f92672">)&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e">// 缓存的数据缓冲区
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span> &lt;span style="color:#66d9ef">private&lt;/span> &lt;span style="color:#66d9ef">val&lt;/span> bufferedData &lt;span style="color:#66d9ef">=&lt;/span> &lt;span style="color:#66d9ef">new&lt;/span> util&lt;span style="color:#f92672">.&lt;/span>&lt;span style="color:#a6e22e">ArrayDeque&lt;/span>&lt;span style="color:#f92672">[&lt;/span>&lt;span style="color:#66d9ef">BufferOrEvent&lt;/span>&lt;span style="color:#f92672">]()&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">override&lt;/span> &lt;span style="color:#66d9ef">def&lt;/span> processBarrier&lt;span style="color:#f92672">(&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> barrier&lt;span style="color:#66d9ef">:&lt;/span> &lt;span style="color:#66d9ef">CheckpointBarrier&lt;/span>&lt;span style="color:#f92672">,&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> channelInfo&lt;span style="color:#66d9ef">:&lt;/span> &lt;span style="color:#66d9ef">InputChannelInfo&lt;/span>&lt;span style="color:#f92672">,&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> bufferReceivedTimestamp&lt;span style="color:#66d9ef">:&lt;/span> &lt;span style="color:#66d9ef">Long&lt;/span>&lt;span style="color:#f92672">)&lt;/span>&lt;span style="color:#66d9ef">:&lt;/span> &lt;span style="color:#66d9ef">Unit&lt;/span> &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#f92672">{&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">val&lt;/span> channelIndex &lt;span style="color:#66d9ef">=&lt;/span> channelInfo&lt;span style="color:#f92672">.&lt;/span>getInputChannelIdx
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">val&lt;/span> checkpointId &lt;span style="color:#66d9ef">=&lt;/span> barrier&lt;span style="color:#f92672">.&lt;/span>getId
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e">// 1. 处理Barrier
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span> &lt;span style="color:#66d9ef">if&lt;/span> &lt;span style="color:#f92672">(&lt;/span>isCheckpointPending&lt;span style="color:#f92672">)&lt;/span> &lt;span style="color:#f92672">{&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e">// 如果已有检查点在进行中
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span> &lt;span style="color:#66d9ef">if&lt;/span> &lt;span style="color:#f92672">(&lt;/span>checkpointId &lt;span style="color:#f92672">&amp;gt;&lt;/span> currentCheckpointId &lt;span style="color:#f92672">||&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">(&lt;/span>checkpointId &lt;span style="color:#f92672">==&lt;/span> currentCheckpointId &lt;span style="color:#f92672">&amp;amp;&amp;amp;&lt;/span> &lt;span style="color:#f92672">!&lt;/span>blockedChannels&lt;span style="color:#f92672">.&lt;/span>get&lt;span style="color:#f92672">(&lt;/span>channelIndex&lt;span style="color:#f92672">)))&lt;/span> &lt;span style="color:#f92672">{&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e">// 阻塞该通道
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span> blockedChannels&lt;span style="color:#f92672">.&lt;/span>set&lt;span style="color:#f92672">(&lt;/span>channelIndex&lt;span style="color:#f92672">)&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">if&lt;/span> &lt;span style="color:#f92672">(&lt;/span>blockedChannels&lt;span style="color:#f92672">.&lt;/span>cardinality&lt;span style="color:#f92672">()&lt;/span> &lt;span style="color:#f92672">==&lt;/span> inputGate&lt;span style="color:#f92672">.&lt;/span>getNumberOfInputChannels&lt;span style="color:#f92672">)&lt;/span> &lt;span style="color:#f92672">{&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e">// 所有通道都被阻塞，触发检查点
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span> &lt;span style="color:#66d9ef">super&lt;/span>&lt;span style="color:#f92672">.&lt;/span>processBarrier&lt;span style="color:#f92672">(&lt;/span>barrier&lt;span style="color:#f92672">,&lt;/span> channelInfo&lt;span style="color:#f92672">,&lt;/span> bufferReceivedTimestamp&lt;span style="color:#f92672">)&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">}&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">}&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">}&lt;/span> &lt;span style="color:#66d9ef">else&lt;/span> &lt;span style="color:#f92672">{&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e">// 第一个Barrier
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span> currentCheckpointId &lt;span style="color:#66d9ef">=&lt;/span> checkpointId
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> blockedChannels&lt;span style="color:#f92672">.&lt;/span>set&lt;span style="color:#f92672">(&lt;/span>channelIndex&lt;span style="color:#f92672">)&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">if&lt;/span> &lt;span style="color:#f92672">(&lt;/span>inputGate&lt;span style="color:#f92672">.&lt;/span>getNumberOfInputChannels &lt;span style="color:#f92672">==&lt;/span> &lt;span style="color:#ae81ff">1&lt;/span>&lt;span style="color:#f92672">)&lt;/span> &lt;span style="color:#f92672">{&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e">// 单输入通道，立即触发
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span> &lt;span style="color:#66d9ef">super&lt;/span>&lt;span style="color:#f92672">.&lt;/span>processBarrier&lt;span style="color:#f92672">(&lt;/span>barrier&lt;span style="color:#f92672">,&lt;/span> channelInfo&lt;span style="color:#f92672">,&lt;/span> bufferReceivedTimestamp&lt;span style="color:#f92672">)&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">}&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">}&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">}&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">override&lt;/span> &lt;span style="color:#66d9ef">protected&lt;/span> &lt;span style="color:#66d9ef">def&lt;/span> notifyCheckpoint&lt;span style="color:#f92672">(&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> barrier&lt;span style="color:#66d9ef">:&lt;/span> &lt;span style="color:#66d9ef">CheckpointBarrier&lt;/span>&lt;span style="color:#f92672">,&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> bufferReceivedTimestamp&lt;span style="color:#66d9ef">:&lt;/span> &lt;span style="color:#66d9ef">Long&lt;/span>&lt;span style="color:#f92672">,&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> checkpointId&lt;span style="color:#66d9ef">:&lt;/span> &lt;span style="color:#66d9ef">Long&lt;/span>&lt;span style="color:#f92672">)&lt;/span>&lt;span style="color:#66d9ef">:&lt;/span> &lt;span style="color:#66d9ef">Unit&lt;/span> &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#f92672">{&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e">// 1. 释放缓存的数据
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span> releaseBufferedData&lt;span style="color:#f92672">()&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e">// 2. 重置状态
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span> reset&lt;span style="color:#f92672">()&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e">// 3. 通知检查点开始
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span> checkpointHandler&lt;span style="color:#f92672">.&lt;/span>triggerCheckpointOnBarrier&lt;span style="color:#f92672">(&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> barrier&lt;span style="color:#f92672">.&lt;/span>asCheckpointBarrier&lt;span style="color:#f92672">(),&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> bufferReceivedTimestamp&lt;span style="color:#f92672">)&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">}&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e">// 缓存来自阻塞通道的数据
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span> &lt;span style="color:#66d9ef">def&lt;/span> bufferReceivedFromBlockedChannel&lt;span style="color:#f92672">(&lt;/span>bufferOrEvent&lt;span style="color:#66d9ef">:&lt;/span> &lt;span style="color:#66d9ef">BufferOrEvent&lt;/span>&lt;span style="color:#f92672">)&lt;/span>&lt;span style="color:#66d9ef">:&lt;/span> &lt;span style="color:#66d9ef">Unit&lt;/span> &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#f92672">{&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">val&lt;/span> channelIndex &lt;span style="color:#66d9ef">=&lt;/span> bufferOrEvent&lt;span style="color:#f92672">.&lt;/span>getChannelInfo&lt;span style="color:#f92672">.&lt;/span>getInputChannelIdx
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">if&lt;/span> &lt;span style="color:#f92672">(&lt;/span>blockedChannels&lt;span style="color:#f92672">.&lt;/span>get&lt;span style="color:#f92672">(&lt;/span>channelIndex&lt;span style="color:#f92672">))&lt;/span> &lt;span style="color:#f92672">{&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e">// 存储到缓冲区
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span> bufferStorage&lt;span style="color:#f92672">.&lt;/span>add&lt;span style="color:#f92672">(&lt;/span>bufferOrEvent&lt;span style="color:#f92672">)&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> bufferedData&lt;span style="color:#f92672">.&lt;/span>add&lt;span style="color:#f92672">(&lt;/span>bufferOrEvent&lt;span style="color:#f92672">)&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">}&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">}&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e">// 释放缓存的数据
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span> &lt;span style="color:#66d9ef">private&lt;/span> &lt;span style="color:#66d9ef">def&lt;/span> releaseBufferedData&lt;span style="color:#f92672">()&lt;/span>&lt;span style="color:#66d9ef">:&lt;/span> &lt;span style="color:#66d9ef">Unit&lt;/span> &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#f92672">{&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">for&lt;/span> &lt;span style="color:#f92672">(&lt;/span>bufferOrEvent &lt;span style="color:#66d9ef">&amp;lt;-&lt;/span> bufferedData&lt;span style="color:#f92672">.&lt;/span>asScala&lt;span style="color:#f92672">)&lt;/span> &lt;span style="color:#f92672">{&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">if&lt;/span> &lt;span style="color:#f92672">(&lt;/span>bufferOrEvent&lt;span style="color:#f92672">.&lt;/span>isBuffer&lt;span style="color:#f92672">)&lt;/span> &lt;span style="color:#f92672">{&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e">// 将缓存的数据发送给下游
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span> outputHandler&lt;span style="color:#f92672">.&lt;/span>emit&lt;span style="color:#f92672">(&lt;/span>bufferOrEvent&lt;span style="color:#f92672">)&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">}&lt;/span> &lt;span style="color:#66d9ef">else&lt;/span> &lt;span style="color:#f92672">{&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e">// 处理事件
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span> outputHandler&lt;span style="color:#f92672">.&lt;/span>handleEvent&lt;span style="color:#f92672">(&lt;/span>bufferOrEvent&lt;span style="color:#f92672">.&lt;/span>getEvent&lt;span style="color:#f92672">,&lt;/span> bufferOrEvent&lt;span style="color:#f92672">.&lt;/span>getChannelInfo&lt;span style="color:#f92672">)&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">}&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">}&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> bufferedData&lt;span style="color:#f92672">.&lt;/span>clear&lt;span style="color:#f92672">()&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">}&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e">// 重置对齐器状态
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span> &lt;span style="color:#66d9ef">private&lt;/span> &lt;span style="color:#66d9ef">def&lt;/span> reset&lt;span style="color:#f92672">()&lt;/span>&lt;span style="color:#66d9ef">:&lt;/span> &lt;span style="color:#66d9ef">Unit&lt;/span> &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#f92672">{&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> blockedChannels&lt;span style="color:#f92672">.&lt;/span>clear&lt;span style="color:#f92672">()&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> currentCheckpointId &lt;span style="color:#66d9ef">=&lt;/span> &lt;span style="color:#f92672">-&lt;/span>&lt;span style="color:#ae81ff">1L&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> bufferedData&lt;span style="color:#f92672">.&lt;/span>clear&lt;span style="color:#f92672">()&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">}&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f92672">}&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">// CheckpointBarrierUnaligner.scala - 至少一次非对齐实现
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>&lt;span style="color:#66d9ef">class&lt;/span> &lt;span style="color:#a6e22e">CheckpointBarrierUnaligner&lt;/span>&lt;span style="color:#f92672">(&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> inputGate&lt;span style="color:#66d9ef">:&lt;/span> &lt;span style="color:#66d9ef">IndexedInputGate&lt;/span>&lt;span style="color:#f92672">,&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> ioExecutor&lt;span style="color:#66d9ef">:&lt;/span> &lt;span style="color:#66d9ef">Executor&lt;/span>&lt;span style="color:#f92672">,&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> channelStateWriter&lt;span style="color:#66d9ef">:&lt;/span> &lt;span style="color:#66d9ef">ChannelStateWriter&lt;/span>&lt;span style="color:#f92672">)&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">extends&lt;/span> &lt;span style="color:#a6e22e">CheckpointBarrierHandler&lt;/span>&lt;span style="color:#f92672">(&lt;/span>inputGate&lt;span style="color:#f92672">,&lt;/span> ioExecutor&lt;span style="color:#f92672">)&lt;/span> &lt;span style="color:#f92672">{&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">override&lt;/span> &lt;span style="color:#66d9ef">def&lt;/span> processBarrier&lt;span style="color:#f92672">(&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> barrier&lt;span style="color:#66d9ef">:&lt;/span> &lt;span style="color:#66d9ef">CheckpointBarrier&lt;/span>&lt;span style="color:#f92672">,&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> channelInfo&lt;span style="color:#66d9ef">:&lt;/span> &lt;span style="color:#66d9ef">InputChannelInfo&lt;/span>&lt;span style="color:#f92672">,&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> bufferReceivedTimestamp&lt;span style="color:#66d9ef">:&lt;/span> &lt;span style="color:#66d9ef">Long&lt;/span>&lt;span style="color:#f92672">)&lt;/span>&lt;span style="color:#66d9ef">:&lt;/span> &lt;span style="color:#66d9ef">Unit&lt;/span> &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#f92672">{&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">val&lt;/span> checkpointId &lt;span style="color:#66d9ef">=&lt;/span> barrier&lt;span style="color:#f92672">.&lt;/span>getId
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">val&lt;/span> channelIndex &lt;span style="color:#66d9ef">=&lt;/span> channelInfo&lt;span style="color:#f92672">.&lt;/span>getInputChannelIdx
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e">// 1. 记录通道状态
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span> &lt;span style="color:#66d9ef">if&lt;/span> &lt;span style="color:#f92672">(!&lt;/span>hasReceivedBarrier&lt;span style="color:#f92672">(&lt;/span>checkpointId&lt;span style="color:#f92672">,&lt;/span> channelIndex&lt;span style="color:#f92672">))&lt;/span> &lt;span style="color:#f92672">{&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> markBarrierReceived&lt;span style="color:#f92672">(&lt;/span>checkpointId&lt;span style="color:#f92672">,&lt;/span> channelIndex&lt;span style="color:#f92672">)&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e">// 2. 快照正在传输的数据
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span> snapshotChannelStates&lt;span style="color:#f92672">(&lt;/span>checkpointId&lt;span style="color:#f92672">,&lt;/span> channelIndex&lt;span style="color:#f92672">)&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e">// 3. 立即触发检查点（不等待对齐）
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span> &lt;span style="color:#66d9ef">if&lt;/span> &lt;span style="color:#f92672">(&lt;/span>shouldTriggerCheckpoint&lt;span style="color:#f92672">(&lt;/span>checkpointId&lt;span style="color:#f92672">))&lt;/span> &lt;span style="color:#f92672">{&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">super&lt;/span>&lt;span style="color:#f92672">.&lt;/span>processBarrier&lt;span style="color:#f92672">(&lt;/span>barrier&lt;span style="color:#f92672">,&lt;/span> channelInfo&lt;span style="color:#f92672">,&lt;/span> bufferReceivedTimestamp&lt;span style="color:#f92672">)&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">}&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">}&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">}&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e">// 快照通道状态
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span> &lt;span style="color:#66d9ef">private&lt;/span> &lt;span style="color:#66d9ef">def&lt;/span> snapshotChannelStates&lt;span style="color:#f92672">(&lt;/span>checkpointId&lt;span style="color:#66d9ef">:&lt;/span> &lt;span style="color:#66d9ef">Long&lt;/span>&lt;span style="color:#f92672">,&lt;/span> channelIndex&lt;span style="color:#66d9ef">:&lt;/span> &lt;span style="color:#66d9ef">Int&lt;/span>&lt;span style="color:#f92672">)&lt;/span>&lt;span style="color:#66d9ef">:&lt;/span> &lt;span style="color:#66d9ef">Unit&lt;/span> &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#f92672">{&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e">// 获取输入通道的正在传输数据
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span> &lt;span style="color:#66d9ef">val&lt;/span> inputChannel &lt;span style="color:#66d9ef">=&lt;/span> inputGate&lt;span style="color:#f92672">.&lt;/span>getChannel&lt;span style="color:#f92672">(&lt;/span>channelIndex&lt;span style="color:#f92672">)&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">val&lt;/span> inflightData &lt;span style="color:#66d9ef">=&lt;/span> inputChannel&lt;span style="color:#f92672">.&lt;/span>getInflightData
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e">// 写入通道状态
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span> channelStateWriter&lt;span style="color:#f92672">.&lt;/span>addInputData&lt;span style="color:#f92672">(&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> checkpointId&lt;span style="color:#f92672">,&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">new&lt;/span> &lt;span style="color:#a6e22e">InputChannelInfo&lt;/span>&lt;span style="color:#f92672">(&lt;/span>inputGate&lt;span style="color:#f92672">.&lt;/span>getGateIndex&lt;span style="color:#f92672">,&lt;/span> channelIndex&lt;span style="color:#f92672">),&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> inflightData&lt;span style="color:#f92672">)&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">}&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">override&lt;/span> &lt;span style="color:#66d9ef">protected&lt;/span> &lt;span style="color:#66d9ef">def&lt;/span> notifyCheckpoint&lt;span style="color:#f92672">(&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> barrier&lt;span style="color:#66d9ef">:&lt;/span> &lt;span style="color:#66d9ef">CheckpointBarrier&lt;/span>&lt;span style="color:#f92672">,&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> bufferReceivedTimestamp&lt;span style="color:#66d9ef">:&lt;/span> &lt;span style="color:#66d9ef">Long&lt;/span>&lt;span style="color:#f92672">,&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> checkpointId&lt;span style="color:#66d9ef">:&lt;/span> &lt;span style="color:#66d9ef">Long&lt;/span>&lt;span style="color:#f92672">)&lt;/span>&lt;span style="color:#66d9ef">:&lt;/span> &lt;span style="color:#66d9ef">Unit&lt;/span> &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#f92672">{&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e">// 非对齐模式下立即触发检查点
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span> checkpointHandler&lt;span style="color:#f92672">.&lt;/span>triggerCheckpointOnBarrier&lt;span style="color:#f92672">(&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> barrier&lt;span style="color:#f92672">.&lt;/span>asCheckpointBarrier&lt;span style="color:#f92672">(),&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> bufferReceivedTimestamp&lt;span style="color:#f92672">)&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">}&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f92672">}&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;hr>
&lt;h2 id="七网络通信系统-1">七、网络通信系统&lt;/h2>
&lt;h3 id="71-网络栈架构">7.1 网络栈架构&lt;/h3>
&lt;h4 id="flink网络栈架构图">Flink网络栈架构图&lt;/h4>
&lt;div class="mermaid">graph TD
A[上游Task] --> B[RecordWriter]
B --> C[ResultPartition]
C --> D[ResultSubpartition]
D --> E[PipelinedSubpartition]
E --> F[NetworkBuffer]
F --> G[Netty Channel]
G --> H[InputChannel]
H --> I[InputGate]
I --> J[RecordReader]
J --> K[下游Task]
L[NetworkBufferPool] --> F
M[LocalBufferPool] --> L
N[CreditBasedFlowControl] --> G
style A fill:#e1f5fe
style F fill:#fff3e0
style K fill:#e8f5e8
style N fill:#ffebee
&lt;/div>
&lt;h4 id="网络栈核心组件">网络栈核心组件&lt;/h4>
&lt;table>
&lt;thead>
&lt;tr>
&lt;th>组件&lt;/th>
&lt;th>功能&lt;/th>
&lt;th>核心职责&lt;/th>
&lt;/tr>
&lt;/thead>
&lt;tbody>
&lt;tr>
&lt;td>&lt;strong>ResultPartition&lt;/strong>&lt;/td>
&lt;td>结果分区&lt;/td>
&lt;td>管理Task的输出数据分区&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;strong>InputGate&lt;/strong>&lt;/td>
&lt;td>输入网关&lt;/td>
&lt;td>聚合多个输入通道的数据&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;strong>NetworkBuffer&lt;/strong>&lt;/td>
&lt;td>网络缓冲区&lt;/td>
&lt;td>数据传输的基本单位&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;strong>CreditFlowControl&lt;/strong>&lt;/td>
&lt;td>流量控制&lt;/td>
&lt;td>基于信用的背压机制&lt;/td>
&lt;/tr>
&lt;/tbody>
&lt;/table>
&lt;h3 id="72-数据传输机制">7.2 数据传输机制&lt;/h3>
&lt;h4 id="数据传输流程图">数据传输流程图&lt;/h4>
&lt;div class="mermaid">graph TD
A[Task产生数据] --> B[序列化数据]
B --> C[写入ResultSubpartition]
C --> D{是否需要网络传输}
D -->|本地| E[LocalInputChannel]
D -->|远程| F[RemoteInputChannel]
F --> G[Netty网络传输]
G --> H[接收端NetworkBuffer]
H --> I[反序列化数据]
I --> J[下游Task消费]
E --> I
K[BackPressure检测] --> C
L[CreditBasedFlowControl] --> F
style A fill:#e1f5fe
style G fill:#fff3e0
style J fill:#e8f5e8
&lt;/div>
&lt;h4 id="resultpartition数据写入源码">ResultPartition数据写入源码&lt;/h4>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-scala" data-lang="scala">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">// ResultPartition.scala - 结果分区数据写入
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>&lt;span style="color:#66d9ef">abstract&lt;/span> &lt;span style="color:#66d9ef">class&lt;/span> &lt;span style="color:#a6e22e">ResultPartition&lt;/span>&lt;span style="color:#f92672">(&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> partitionId&lt;span style="color:#66d9ef">:&lt;/span> &lt;span style="color:#66d9ef">ResultPartitionID&lt;/span>&lt;span style="color:#f92672">,&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> partitionType&lt;span style="color:#66d9ef">:&lt;/span> &lt;span style="color:#66d9ef">ResultPartitionType&lt;/span>&lt;span style="color:#f92672">,&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> numberOfSubpartitions&lt;span style="color:#66d9ef">:&lt;/span> &lt;span style="color:#66d9ef">Int&lt;/span>&lt;span style="color:#f92672">,&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> numberOfChannels&lt;span style="color:#66d9ef">:&lt;/span> &lt;span style="color:#66d9ef">Int&lt;/span>&lt;span style="color:#f92672">,&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> resultPartitionManager&lt;span style="color:#66d9ef">:&lt;/span> &lt;span style="color:#66d9ef">ResultPartitionManager&lt;/span>&lt;span style="color:#f92672">,&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> partitionDataAvailabilityListener&lt;span style="color:#66d9ef">:&lt;/span> &lt;span style="color:#66d9ef">PartitionDataAvailabilityListener&lt;/span>&lt;span style="color:#f92672">,&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> bufferPoolFactory&lt;span style="color:#66d9ef">:&lt;/span> &lt;span style="color:#f92672">()&lt;/span> &lt;span style="color:#f92672">=&amp;gt;&lt;/span> &lt;span style="color:#a6e22e">BufferPool&lt;/span>&lt;span style="color:#f92672">)&lt;/span> &lt;span style="color:#f92672">{&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e">// 子分区数组
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span> &lt;span style="color:#66d9ef">protected&lt;/span> &lt;span style="color:#66d9ef">val&lt;/span> subpartitions&lt;span style="color:#66d9ef">:&lt;/span> &lt;span style="color:#66d9ef">Array&lt;/span>&lt;span style="color:#f92672">[&lt;/span>&lt;span style="color:#66d9ef">ResultSubpartition&lt;/span>&lt;span style="color:#f92672">]&lt;/span> &lt;span style="color:#66d9ef">=&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">new&lt;/span> &lt;span style="color:#a6e22e">Array&lt;/span>&lt;span style="color:#f92672">[&lt;/span>&lt;span style="color:#66d9ef">ResultSubpartition&lt;/span>&lt;span style="color:#f92672">](&lt;/span>numberOfSubpartitions&lt;span style="color:#f92672">)&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e">// 缓冲池
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span> &lt;span style="color:#66d9ef">private&lt;/span> &lt;span style="color:#66d9ef">var&lt;/span> bufferPool&lt;span style="color:#66d9ef">:&lt;/span> &lt;span style="color:#66d9ef">BufferPool&lt;/span> &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#66d9ef">_&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e">// 分区写入器
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span> &lt;span style="color:#66d9ef">private&lt;/span> &lt;span style="color:#66d9ef">val&lt;/span> partitionWriter &lt;span style="color:#66d9ef">=&lt;/span> createSubpartitionWriter&lt;span style="color:#f92672">()&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e">// 写入数据到指定子分区
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span> &lt;span style="color:#66d9ef">def&lt;/span> emitRecord&lt;span style="color:#f92672">(&lt;/span>record&lt;span style="color:#66d9ef">:&lt;/span> &lt;span style="color:#66d9ef">ByteBuffer&lt;/span>&lt;span style="color:#f92672">,&lt;/span> targetChannel&lt;span style="color:#66d9ef">:&lt;/span> &lt;span style="color:#66d9ef">Int&lt;/span>&lt;span style="color:#f92672">)&lt;/span>&lt;span style="color:#66d9ef">:&lt;/span> &lt;span style="color:#66d9ef">Unit&lt;/span> &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#f92672">{&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> checkArgument&lt;span style="color:#f92672">(&lt;/span>targetChannel &lt;span style="color:#f92672">&amp;lt;&lt;/span> numberOfSubpartitions&lt;span style="color:#f92672">,&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e6db74">s&amp;#34;Target channel &lt;/span>&lt;span style="color:#e6db74">$targetChannel&lt;/span>&lt;span style="color:#e6db74"> exceeds number of subpartitions &lt;/span>&lt;span style="color:#e6db74">$numberOfSubpartitions&lt;/span>&lt;span style="color:#e6db74">&amp;#34;&lt;/span>&lt;span style="color:#f92672">)&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e">// 1. 获取目标子分区
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span> &lt;span style="color:#66d9ef">val&lt;/span> targetSubpartition &lt;span style="color:#66d9ef">=&lt;/span> subpartitions&lt;span style="color:#f92672">(&lt;/span>targetChannel&lt;span style="color:#f92672">)&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e">// 2. 请求网络缓冲区
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span> &lt;span style="color:#66d9ef">val&lt;/span> buffer &lt;span style="color:#66d9ef">=&lt;/span> bufferPool&lt;span style="color:#f92672">.&lt;/span>requestBuffer&lt;span style="color:#f92672">()&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">if&lt;/span> &lt;span style="color:#f92672">(&lt;/span>buffer &lt;span style="color:#f92672">!=&lt;/span> &lt;span style="color:#66d9ef">null&lt;/span>&lt;span style="color:#f92672">)&lt;/span> &lt;span style="color:#f92672">{&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">try&lt;/span> &lt;span style="color:#f92672">{&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e">// 3. 将记录写入缓冲区
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span> buffer&lt;span style="color:#f92672">.&lt;/span>writeBytes&lt;span style="color:#f92672">(&lt;/span>record&lt;span style="color:#f92672">)&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e">// 4. 添加到子分区
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span> targetSubpartition&lt;span style="color:#f92672">.&lt;/span>add&lt;span style="color:#f92672">(&lt;/span>buffer&lt;span style="color:#f92672">,&lt;/span> &lt;span style="color:#a6e22e">Buffer&lt;/span>&lt;span style="color:#f92672">.&lt;/span>&lt;span style="color:#a6e22e">DataType&lt;/span>&lt;span style="color:#f92672">.&lt;/span>&lt;span style="color:#a6e22e">DATA_BUFFER&lt;/span>&lt;span style="color:#f92672">)&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e">// 5. 通知数据可用
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span> partitionDataAvailabilityListener&lt;span style="color:#f92672">.&lt;/span>notifyDataAvailable&lt;span style="color:#f92672">()&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">}&lt;/span> &lt;span style="color:#66d9ef">catch&lt;/span> &lt;span style="color:#f92672">{&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">case&lt;/span> e&lt;span style="color:#66d9ef">:&lt;/span> &lt;span style="color:#66d9ef">Exception&lt;/span> &lt;span style="color:#f92672">=&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> buffer&lt;span style="color:#f92672">.&lt;/span>recycleBuffer&lt;span style="color:#f92672">()&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">throw&lt;/span> e
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">}&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">}&lt;/span> &lt;span style="color:#66d9ef">else&lt;/span> &lt;span style="color:#f92672">{&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e">// 缓冲区不足，触发背压
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span> &lt;span style="color:#66d9ef">throw&lt;/span> &lt;span style="color:#66d9ef">new&lt;/span> &lt;span style="color:#a6e22e">RuntimeException&lt;/span>&lt;span style="color:#f92672">(&lt;/span>&lt;span style="color:#e6db74">&amp;#34;No buffer available for data emission&amp;#34;&lt;/span>&lt;span style="color:#f92672">)&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">}&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">}&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e">// 写入广播数据
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span> &lt;span style="color:#66d9ef">def&lt;/span> broadcastRecord&lt;span style="color:#f92672">(&lt;/span>record&lt;span style="color:#66d9ef">:&lt;/span> &lt;span style="color:#66d9ef">ByteBuffer&lt;/span>&lt;span style="color:#f92672">)&lt;/span>&lt;span style="color:#66d9ef">:&lt;/span> &lt;span style="color:#66d9ef">Unit&lt;/span> &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#f92672">{&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">for&lt;/span> &lt;span style="color:#f92672">(&lt;/span>i &lt;span style="color:#66d9ef">&amp;lt;-&lt;/span> subpartitions&lt;span style="color:#f92672">.&lt;/span>indices&lt;span style="color:#f92672">)&lt;/span> &lt;span style="color:#f92672">{&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> emitRecord&lt;span style="color:#f92672">(&lt;/span>record&lt;span style="color:#f92672">,&lt;/span> i&lt;span style="color:#f92672">)&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">}&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">}&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e">// 结束分区写入
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span> &lt;span style="color:#66d9ef">def&lt;/span> finish&lt;span style="color:#f92672">()&lt;/span>&lt;span style="color:#66d9ef">:&lt;/span> &lt;span style="color:#66d9ef">Unit&lt;/span> &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#f92672">{&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">for&lt;/span> &lt;span style="color:#f92672">(&lt;/span>subpartition &lt;span style="color:#66d9ef">&amp;lt;-&lt;/span> subpartitions&lt;span style="color:#f92672">)&lt;/span> &lt;span style="color:#f92672">{&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> subpartition&lt;span style="color:#f92672">.&lt;/span>finish&lt;span style="color:#f92672">()&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">}&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e">// 通知所有消费者分区已完成
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span> partitionDataAvailabilityListener&lt;span style="color:#f92672">.&lt;/span>notifyPartitionFinished&lt;span style="color:#f92672">()&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">}&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e">// 创建子分区视图
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span> &lt;span style="color:#66d9ef">def&lt;/span> createSubpartitionView&lt;span style="color:#f92672">(&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> subpartitionId&lt;span style="color:#66d9ef">:&lt;/span> &lt;span style="color:#66d9ef">Int&lt;/span>&lt;span style="color:#f92672">,&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> bufferAvailabilityListener&lt;span style="color:#66d9ef">:&lt;/span> &lt;span style="color:#66d9ef">BufferAvailabilityListener&lt;/span>&lt;span style="color:#f92672">)&lt;/span>&lt;span style="color:#66d9ef">:&lt;/span> &lt;span style="color:#66d9ef">ResultSubpartitionView&lt;/span> &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#f92672">{&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> checkArgument&lt;span style="color:#f92672">(&lt;/span>subpartitionId &lt;span style="color:#f92672">&amp;lt;&lt;/span> numberOfSubpartitions&lt;span style="color:#f92672">,&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e6db74">s&amp;#34;Subpartition &lt;/span>&lt;span style="color:#e6db74">$subpartitionId&lt;/span>&lt;span style="color:#e6db74"> does not exist&amp;#34;&lt;/span>&lt;span style="color:#f92672">)&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">val&lt;/span> subpartition &lt;span style="color:#66d9ef">=&lt;/span> subpartitions&lt;span style="color:#f92672">(&lt;/span>subpartitionId&lt;span style="color:#f92672">)&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> subpartition&lt;span style="color:#f92672">.&lt;/span>createReadView&lt;span style="color:#f92672">(&lt;/span>bufferAvailabilityListener&lt;span style="color:#f92672">)&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">}&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f92672">}&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">// PipelinedSubpartition.scala - 管道化子分区实现
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>&lt;span style="color:#66d9ef">class&lt;/span> &lt;span style="color:#a6e22e">PipelinedSubpartition&lt;/span>&lt;span style="color:#f92672">(&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> index&lt;span style="color:#66d9ef">:&lt;/span> &lt;span style="color:#66d9ef">Int&lt;/span>&lt;span style="color:#f92672">,&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> parent&lt;span style="color:#66d9ef">:&lt;/span> &lt;span style="color:#66d9ef">ResultPartition&lt;/span>&lt;span style="color:#f92672">)&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">extends&lt;/span> &lt;span style="color:#a6e22e">ResultSubpartition&lt;/span>&lt;span style="color:#f92672">(&lt;/span>index&lt;span style="color:#f92672">,&lt;/span> parent&lt;span style="color:#f92672">)&lt;/span> &lt;span style="color:#f92672">{&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e">// 缓冲区队列
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span> &lt;span style="color:#66d9ef">private&lt;/span> &lt;span style="color:#66d9ef">val&lt;/span> buffers &lt;span style="color:#66d9ef">=&lt;/span> &lt;span style="color:#66d9ef">new&lt;/span> &lt;span style="color:#a6e22e">ArrayDeque&lt;/span>&lt;span style="color:#f92672">[&lt;/span>&lt;span style="color:#66d9ef">BufferConsumer&lt;/span>&lt;span style="color:#f92672">]()&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e">// 读取视图
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span> &lt;span style="color:#66d9ef">private&lt;/span> &lt;span style="color:#66d9ef">var&lt;/span> readView&lt;span style="color:#66d9ef">:&lt;/span> &lt;span style="color:#66d9ef">PipelinedSubpartitionView&lt;/span> &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#66d9ef">_&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e">// 是否已完成
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span> &lt;span style="color:#a6e22e">@volatile&lt;/span> &lt;span style="color:#66d9ef">private&lt;/span> &lt;span style="color:#66d9ef">var&lt;/span> isFinished &lt;span style="color:#66d9ef">=&lt;/span> &lt;span style="color:#66d9ef">false&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e">// 添加缓冲区
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span> &lt;span style="color:#66d9ef">override&lt;/span> &lt;span style="color:#66d9ef">def&lt;/span> add&lt;span style="color:#f92672">(&lt;/span>bufferConsumer&lt;span style="color:#66d9ef">:&lt;/span> &lt;span style="color:#66d9ef">BufferConsumer&lt;/span>&lt;span style="color:#f92672">,&lt;/span> dataType&lt;span style="color:#66d9ef">:&lt;/span> &lt;span style="color:#66d9ef">Buffer.DataType&lt;/span>&lt;span style="color:#f92672">)&lt;/span>&lt;span style="color:#66d9ef">:&lt;/span> &lt;span style="color:#66d9ef">Boolean&lt;/span> &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#f92672">{&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> synchronized &lt;span style="color:#f92672">{&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">if&lt;/span> &lt;span style="color:#f92672">(&lt;/span>isFinished&lt;span style="color:#f92672">)&lt;/span> &lt;span style="color:#f92672">{&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> bufferConsumer&lt;span style="color:#f92672">.&lt;/span>close&lt;span style="color:#f92672">()&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">return&lt;/span> &lt;span style="color:#66d9ef">false&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">}&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e">// 1. 添加到队列
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span> buffers&lt;span style="color:#f92672">.&lt;/span>add&lt;span style="color:#f92672">(&lt;/span>bufferConsumer&lt;span style="color:#f92672">)&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e">// 2. 通知读取视图数据可用
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span> &lt;span style="color:#66d9ef">if&lt;/span> &lt;span style="color:#f92672">(&lt;/span>readView &lt;span style="color:#f92672">!=&lt;/span> &lt;span style="color:#66d9ef">null&lt;/span>&lt;span style="color:#f92672">)&lt;/span> &lt;span style="color:#f92672">{&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> readView&lt;span style="color:#f92672">.&lt;/span>notifyDataAvailable&lt;span style="color:#f92672">()&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">}&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">true&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">}&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">}&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e">// 创建读取视图
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span> &lt;span style="color:#66d9ef">override&lt;/span> &lt;span style="color:#66d9ef">def&lt;/span> createReadView&lt;span style="color:#f92672">(&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> availabilityListener&lt;span style="color:#66d9ef">:&lt;/span> &lt;span style="color:#66d9ef">BufferAvailabilityListener&lt;/span>&lt;span style="color:#f92672">)&lt;/span>&lt;span style="color:#66d9ef">:&lt;/span> &lt;span style="color:#66d9ef">ResultSubpartitionView&lt;/span> &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#f92672">{&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> synchronized &lt;span style="color:#f92672">{&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> checkState&lt;span style="color:#f92672">(&lt;/span>readView &lt;span style="color:#f92672">==&lt;/span> &lt;span style="color:#66d9ef">null&lt;/span>&lt;span style="color:#f92672">,&lt;/span> &lt;span style="color:#e6db74">&amp;#34;Subpartition is being consumed&amp;#34;&lt;/span>&lt;span style="color:#f92672">)&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> readView &lt;span style="color:#66d9ef">=&lt;/span> &lt;span style="color:#66d9ef">new&lt;/span> &lt;span style="color:#a6e22e">PipelinedSubpartitionView&lt;/span>&lt;span style="color:#f92672">(&lt;/span>&lt;span style="color:#66d9ef">this&lt;/span>&lt;span style="color:#f92672">,&lt;/span> availabilityListener&lt;span style="color:#f92672">)&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">if&lt;/span> &lt;span style="color:#f92672">(!&lt;/span>buffers&lt;span style="color:#f92672">.&lt;/span>isEmpty&lt;span style="color:#f92672">)&lt;/span> &lt;span style="color:#f92672">{&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> readView&lt;span style="color:#f92672">.&lt;/span>notifyDataAvailable&lt;span style="color:#f92672">()&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">}&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> readView
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">}&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">}&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e">// 读取下一个缓冲区
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span> &lt;span style="color:#66d9ef">def&lt;/span> pollBuffer&lt;span style="color:#f92672">()&lt;/span>&lt;span style="color:#66d9ef">:&lt;/span> &lt;span style="color:#66d9ef">BufferAndBacklog&lt;/span> &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#f92672">{&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> synchronized &lt;span style="color:#f92672">{&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">val&lt;/span> buffer &lt;span style="color:#66d9ef">=&lt;/span> buffers&lt;span style="color:#f92672">.&lt;/span>poll&lt;span style="color:#f92672">()&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">if&lt;/span> &lt;span style="color:#f92672">(&lt;/span>buffer &lt;span style="color:#f92672">!=&lt;/span> &lt;span style="color:#66d9ef">null&lt;/span>&lt;span style="color:#f92672">)&lt;/span> &lt;span style="color:#f92672">{&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">val&lt;/span> backlog &lt;span style="color:#66d9ef">=&lt;/span> buffers&lt;span style="color:#f92672">.&lt;/span>size&lt;span style="color:#f92672">()&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">new&lt;/span> &lt;span style="color:#a6e22e">BufferAndBacklog&lt;/span>&lt;span style="color:#f92672">(&lt;/span>buffer&lt;span style="color:#f92672">.&lt;/span>build&lt;span style="color:#f92672">(),&lt;/span> backlog&lt;span style="color:#f92672">,&lt;/span> &lt;span style="color:#a6e22e">Buffer&lt;/span>&lt;span style="color:#f92672">.&lt;/span>&lt;span style="color:#a6e22e">DataType&lt;/span>&lt;span style="color:#f92672">.&lt;/span>&lt;span style="color:#a6e22e">DATA_BUFFER&lt;/span>&lt;span style="color:#f92672">,&lt;/span> &lt;span style="color:#ae81ff">0&lt;/span>&lt;span style="color:#f92672">)&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">}&lt;/span> &lt;span style="color:#66d9ef">else&lt;/span> &lt;span style="color:#66d9ef">if&lt;/span> &lt;span style="color:#f92672">(&lt;/span>isFinished&lt;span style="color:#f92672">)&lt;/span> &lt;span style="color:#f92672">{&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">BufferAndBacklog&lt;/span>&lt;span style="color:#f92672">.&lt;/span>&lt;span style="color:#a6e22e">FINISHED&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">}&lt;/span> &lt;span style="color:#66d9ef">else&lt;/span> &lt;span style="color:#f92672">{&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">null&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">}&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">}&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">}&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e">// 完成子分区
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span> &lt;span style="color:#66d9ef">override&lt;/span> &lt;span style="color:#66d9ef">def&lt;/span> finish&lt;span style="color:#f92672">()&lt;/span>&lt;span style="color:#66d9ef">:&lt;/span> &lt;span style="color:#66d9ef">Unit&lt;/span> &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#f92672">{&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> synchronized &lt;span style="color:#f92672">{&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> isFinished &lt;span style="color:#66d9ef">=&lt;/span> &lt;span style="color:#66d9ef">true&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">if&lt;/span> &lt;span style="color:#f92672">(&lt;/span>readView &lt;span style="color:#f92672">!=&lt;/span> &lt;span style="color:#66d9ef">null&lt;/span>&lt;span style="color:#f92672">)&lt;/span> &lt;span style="color:#f92672">{&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> readView&lt;span style="color:#f92672">.&lt;/span>notifyDataAvailable&lt;span style="color:#f92672">()&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">}&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">}&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">}&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e">// 获取缓冲区积压数量
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span> &lt;span style="color:#66d9ef">def&lt;/span> getBuffersBacklog&lt;span style="color:#66d9ef">:&lt;/span> &lt;span style="color:#66d9ef">Int&lt;/span> &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#f92672">{&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> synchronized &lt;span style="color:#f92672">{&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> buffers&lt;span style="color:#f92672">.&lt;/span>size&lt;span style="color:#f92672">()&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">}&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">}&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f92672">}&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h3 id="73-背压处理">7.3 背压处理&lt;/h3>
&lt;h4 id="信用流量控制机制">信用流量控制机制&lt;/h4>
&lt;div class="mermaid">graph TD
A[下游Task] --> B[计算可用Credit]
B --> C[发送CreditAnnouncement]
C --> D[上游接收Credit]
D --> E{是否有足够Credit}
E -->|有| F[发送数据]
E -->|无| G[暂停发送]
F --> H[消费Credit]
H --> I[更新Available Credit]
I --> J[下游处理数据]
J --> K[释放Buffer]
K --> B
G --> L[等待新Credit]
L --> D
style A fill:#e1f5fe
style E fill:#fff3e0
style J fill:#e8f5e8
&lt;/div>
&lt;h4 id="creditbasedflowcontrol源码">CreditBasedFlowControl源码&lt;/h4>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-scala" data-lang="scala">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">// CreditBasedPartitionRequestClientHandler.scala - 基于信用的流量控制
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>&lt;span style="color:#66d9ef">class&lt;/span> &lt;span style="color:#a6e22e">CreditBasedPartitionRequestClientHandler&lt;/span> &lt;span style="color:#66d9ef">extends&lt;/span> &lt;span style="color:#a6e22e">ChannelInboundHandlerAdapter&lt;/span> &lt;span style="color:#f92672">{&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e">// 输入通道映射
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span> &lt;span style="color:#66d9ef">private&lt;/span> &lt;span style="color:#66d9ef">val&lt;/span> inputChannels &lt;span style="color:#66d9ef">=&lt;/span> &lt;span style="color:#66d9ef">new&lt;/span> &lt;span style="color:#a6e22e">ConcurrentHashMap&lt;/span>&lt;span style="color:#f92672">[&lt;/span>&lt;span style="color:#66d9ef">InputChannelID&lt;/span>, &lt;span style="color:#66d9ef">RemoteInputChannel&lt;/span>&lt;span style="color:#f92672">]()&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e">// 网络客户端
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span> &lt;span style="color:#66d9ef">private&lt;/span> &lt;span style="color:#66d9ef">var&lt;/span> networkClient&lt;span style="color:#66d9ef">:&lt;/span> &lt;span style="color:#66d9ef">NettyClient&lt;/span> &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#66d9ef">_&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e">// 处理接收到的消息
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span> &lt;span style="color:#66d9ef">override&lt;/span> &lt;span style="color:#66d9ef">def&lt;/span> channelRead&lt;span style="color:#f92672">(&lt;/span>ctx&lt;span style="color:#66d9ef">:&lt;/span> &lt;span style="color:#66d9ef">ChannelHandlerContext&lt;/span>&lt;span style="color:#f92672">,&lt;/span> msg&lt;span style="color:#66d9ef">:&lt;/span> &lt;span style="color:#66d9ef">AnyRef&lt;/span>&lt;span style="color:#f92672">)&lt;/span>&lt;span style="color:#66d9ef">:&lt;/span> &lt;span style="color:#66d9ef">Unit&lt;/span> &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#f92672">{&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">try&lt;/span> &lt;span style="color:#f92672">{&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> msg &lt;span style="color:#66d9ef">match&lt;/span> &lt;span style="color:#f92672">{&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">case&lt;/span> bufferResponse&lt;span style="color:#66d9ef">:&lt;/span> &lt;span style="color:#66d9ef">NettyMessage.BufferResponse&lt;/span> &lt;span style="color:#f92672">=&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> handleBufferResponse&lt;span style="color:#f92672">(&lt;/span>bufferResponse&lt;span style="color:#f92672">)&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">case&lt;/span> backlogMessage&lt;span style="color:#66d9ef">:&lt;/span> &lt;span style="color:#66d9ef">NettyMessage.BacklogAnnouncement&lt;/span> &lt;span style="color:#f92672">=&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> handleBacklogAnnouncement&lt;span style="color:#f92672">(&lt;/span>backlogMessage&lt;span style="color:#f92672">)&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">case&lt;/span> errorResponse&lt;span style="color:#66d9ef">:&lt;/span> &lt;span style="color:#66d9ef">NettyMessage.ErrorResponse&lt;/span> &lt;span style="color:#f92672">=&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> handleErrorResponse&lt;span style="color:#f92672">(&lt;/span>errorResponse&lt;span style="color:#f92672">)&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">case&lt;/span> &lt;span style="color:#66d9ef">_&lt;/span> &lt;span style="color:#66d9ef">=&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">throw&lt;/span> &lt;span style="color:#66d9ef">new&lt;/span> &lt;span style="color:#a6e22e">IllegalStateException&lt;/span>&lt;span style="color:#f92672">(&lt;/span>&lt;span style="color:#e6db74">s&amp;#34;Unknown message type: &lt;/span>&lt;span style="color:#e6db74">${&lt;/span>msg&lt;span style="color:#f92672">.&lt;/span>getClass&lt;span style="color:#e6db74">}&lt;/span>&lt;span style="color:#e6db74">&amp;#34;&lt;/span>&lt;span style="color:#f92672">)&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">}&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">}&lt;/span> &lt;span style="color:#66d9ef">catch&lt;/span> &lt;span style="color:#f92672">{&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">case&lt;/span> e&lt;span style="color:#66d9ef">:&lt;/span> &lt;span style="color:#66d9ef">Exception&lt;/span> &lt;span style="color:#f92672">=&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> exceptionCaught&lt;span style="color:#f92672">(&lt;/span>ctx&lt;span style="color:#f92672">,&lt;/span> e&lt;span style="color:#f92672">)&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">}&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">}&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e">// 处理缓冲区响应
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span> &lt;span style="color:#66d9ef">private&lt;/span> &lt;span style="color:#66d9ef">def&lt;/span> handleBufferResponse&lt;span style="color:#f92672">(&lt;/span>bufferResponse&lt;span style="color:#66d9ef">:&lt;/span> &lt;span style="color:#66d9ef">NettyMessage.BufferResponse&lt;/span>&lt;span style="color:#f92672">)&lt;/span>&lt;span style="color:#66d9ef">:&lt;/span> &lt;span style="color:#66d9ef">Unit&lt;/span> &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#f92672">{&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">val&lt;/span> receiverId &lt;span style="color:#66d9ef">=&lt;/span> bufferResponse&lt;span style="color:#f92672">.&lt;/span>receiverId
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">val&lt;/span> inputChannel &lt;span style="color:#66d9ef">=&lt;/span> inputChannels&lt;span style="color:#f92672">.&lt;/span>get&lt;span style="color:#f92672">(&lt;/span>receiverId&lt;span style="color:#f92672">)&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">if&lt;/span> &lt;span style="color:#f92672">(&lt;/span>inputChannel &lt;span style="color:#f92672">!=&lt;/span> &lt;span style="color:#66d9ef">null&lt;/span>&lt;span style="color:#f92672">)&lt;/span> &lt;span style="color:#f92672">{&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e">// 处理接收到的缓冲区
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span> inputChannel&lt;span style="color:#f92672">.&lt;/span>onBuffer&lt;span style="color:#f92672">(&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> bufferResponse&lt;span style="color:#f92672">.&lt;/span>buffer&lt;span style="color:#f92672">,&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> bufferResponse&lt;span style="color:#f92672">.&lt;/span>sequenceNumber&lt;span style="color:#f92672">,&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> bufferResponse&lt;span style="color:#f92672">.&lt;/span>backlog&lt;span style="color:#f92672">)&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">}&lt;/span> &lt;span style="color:#66d9ef">else&lt;/span> &lt;span style="color:#f92672">{&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e">// 回收未消费的缓冲区
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span> bufferResponse&lt;span style="color:#f92672">.&lt;/span>buffer&lt;span style="color:#f92672">.&lt;/span>recycleBuffer&lt;span style="color:#f92672">()&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">}&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">}&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e">// 处理积压通知
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span> &lt;span style="color:#66d9ef">private&lt;/span> &lt;span style="color:#66d9ef">def&lt;/span> handleBacklogAnnouncement&lt;span style="color:#f92672">(&lt;/span>backlogMessage&lt;span style="color:#66d9ef">:&lt;/span> &lt;span style="color:#66d9ef">NettyMessage.BacklogAnnouncement&lt;/span>&lt;span style="color:#f92672">)&lt;/span>&lt;span style="color:#66d9ef">:&lt;/span> &lt;span style="color:#66d9ef">Unit&lt;/span> &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#f92672">{&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">val&lt;/span> receiverId &lt;span style="color:#66d9ef">=&lt;/span> backlogMessage&lt;span style="color:#f92672">.&lt;/span>receiverId
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">val&lt;/span> inputChannel &lt;span style="color:#66d9ef">=&lt;/span> inputChannels&lt;span style="color:#f92672">.&lt;/span>get&lt;span style="color:#f92672">(&lt;/span>receiverId&lt;span style="color:#f92672">)&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">if&lt;/span> &lt;span style="color:#f92672">(&lt;/span>inputChannel &lt;span style="color:#f92672">!=&lt;/span> &lt;span style="color:#66d9ef">null&lt;/span>&lt;span style="color:#f92672">)&lt;/span> &lt;span style="color:#f92672">{&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> inputChannel&lt;span style="color:#f92672">.&lt;/span>onSenderBacklog&lt;span style="color:#f92672">(&lt;/span>backlogMessage&lt;span style="color:#f92672">.&lt;/span>backlog&lt;span style="color:#f92672">)&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">}&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">}&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e">// 添加输入通道
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span> &lt;span style="color:#66d9ef">def&lt;/span> addInputChannel&lt;span style="color:#f92672">(&lt;/span>inputChannel&lt;span style="color:#66d9ef">:&lt;/span> &lt;span style="color:#66d9ef">RemoteInputChannel&lt;/span>&lt;span style="color:#f92672">)&lt;/span>&lt;span style="color:#66d9ef">:&lt;/span> &lt;span style="color:#66d9ef">Unit&lt;/span> &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#f92672">{&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> inputChannels&lt;span style="color:#f92672">.&lt;/span>put&lt;span style="color:#f92672">(&lt;/span>inputChannel&lt;span style="color:#f92672">.&lt;/span>getInputChannelId&lt;span style="color:#f92672">,&lt;/span> inputChannel&lt;span style="color:#f92672">)&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e">// 发送初始分区请求
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span> &lt;span style="color:#66d9ef">val&lt;/span> partitionRequest &lt;span style="color:#66d9ef">=&lt;/span> &lt;span style="color:#66d9ef">new&lt;/span> &lt;span style="color:#a6e22e">NettyMessage&lt;/span>&lt;span style="color:#f92672">.&lt;/span>&lt;span style="color:#a6e22e">PartitionRequest&lt;/span>&lt;span style="color:#f92672">(&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> inputChannel&lt;span style="color:#f92672">.&lt;/span>getPartitionId&lt;span style="color:#f92672">,&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> inputChannel&lt;span style="color:#f92672">.&lt;/span>getConsumedSubpartitionIndex&lt;span style="color:#f92672">,&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> inputChannel&lt;span style="color:#f92672">.&lt;/span>getInputChannelId&lt;span style="color:#f92672">,&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> inputChannel&lt;span style="color:#f92672">.&lt;/span>getInitialCredit&lt;span style="color:#f92672">)&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> networkClient&lt;span style="color:#f92672">.&lt;/span>sendMessage&lt;span style="color:#f92672">(&lt;/span>partitionRequest&lt;span style="color:#f92672">)&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">}&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e">// 移除输入通道
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span> &lt;span style="color:#66d9ef">def&lt;/span> removeInputChannel&lt;span style="color:#f92672">(&lt;/span>inputChannel&lt;span style="color:#66d9ef">:&lt;/span> &lt;span style="color:#66d9ef">RemoteInputChannel&lt;/span>&lt;span style="color:#f92672">)&lt;/span>&lt;span style="color:#66d9ef">:&lt;/span> &lt;span style="color:#66d9ef">Unit&lt;/span> &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#f92672">{&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> inputChannels&lt;span style="color:#f92672">.&lt;/span>remove&lt;span style="color:#f92672">(&lt;/span>inputChannel&lt;span style="color:#f92672">.&lt;/span>getInputChannelId&lt;span style="color:#f92672">)&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e">// 发送取消分区请求
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span> &lt;span style="color:#66d9ef">val&lt;/span> cancelRequest &lt;span style="color:#66d9ef">=&lt;/span> &lt;span style="color:#66d9ef">new&lt;/span> &lt;span style="color:#a6e22e">NettyMessage&lt;/span>&lt;span style="color:#f92672">.&lt;/span>&lt;span style="color:#a6e22e">CancelPartitionRequest&lt;/span>&lt;span style="color:#f92672">(&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> inputChannel&lt;span style="color:#f92672">.&lt;/span>getInputChannelId&lt;span style="color:#f92672">)&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> networkClient&lt;span style="color:#f92672">.&lt;/span>sendMessage&lt;span style="color:#f92672">(&lt;/span>cancelRequest&lt;span style="color:#f92672">)&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">}&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f92672">}&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">// RemoteInputChannel.scala - 远程输入通道
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>&lt;span style="color:#66d9ef">class&lt;/span> &lt;span style="color:#a6e22e">RemoteInputChannel&lt;/span>&lt;span style="color:#f92672">(&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> connectionManager&lt;span style="color:#66d9ef">:&lt;/span> &lt;span style="color:#66d9ef">ConnectionManager&lt;/span>&lt;span style="color:#f92672">,&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> partitionId&lt;span style="color:#66d9ef">:&lt;/span> &lt;span style="color:#66d9ef">ResultPartitionID&lt;/span>&lt;span style="color:#f92672">,&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> inputChannelId&lt;span style="color:#66d9ef">:&lt;/span> &lt;span style="color:#66d9ef">InputChannelID&lt;/span>&lt;span style="color:#f92672">,&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> initialBackoff&lt;span style="color:#66d9ef">:&lt;/span> &lt;span style="color:#66d9ef">Int&lt;/span>&lt;span style="color:#f92672">,&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> maxBackoff&lt;span style="color:#66d9ef">:&lt;/span> &lt;span style="color:#66d9ef">Int&lt;/span>&lt;span style="color:#f92672">,&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> networkBuffersPerChannel&lt;span style="color:#66d9ef">:&lt;/span> &lt;span style="color:#66d9ef">Int&lt;/span>&lt;span style="color:#f92672">)&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">extends&lt;/span> &lt;span style="color:#a6e22e">InputChannel&lt;/span> &lt;span style="color:#f92672">{&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e">// 可用信用数
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span> &lt;span style="color:#a6e22e">@volatile&lt;/span> &lt;span style="color:#66d9ef">private&lt;/span> &lt;span style="color:#66d9ef">var&lt;/span> unannouncedCredit &lt;span style="color:#66d9ef">=&lt;/span> networkBuffersPerChannel
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e">// 缓冲区队列
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span> &lt;span style="color:#66d9ef">private&lt;/span> &lt;span style="color:#66d9ef">val&lt;/span> receivedBuffers &lt;span style="color:#66d9ef">=&lt;/span> &lt;span style="color:#66d9ef">new&lt;/span> &lt;span style="color:#a6e22e">ArrayDeque&lt;/span>&lt;span style="color:#f92672">[&lt;/span>&lt;span style="color:#66d9ef">Buffer&lt;/span>&lt;span style="color:#f92672">]()&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e">// 序列号计数器
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span> &lt;span style="color:#66d9ef">private&lt;/span> &lt;span style="color:#66d9ef">var&lt;/span> expectedSequenceNumber &lt;span style="color:#66d9ef">=&lt;/span> &lt;span style="color:#ae81ff">0&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e">// 请求下一个缓冲区
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span> &lt;span style="color:#66d9ef">override&lt;/span> &lt;span style="color:#66d9ef">def&lt;/span> getNextBuffer&lt;span style="color:#f92672">()&lt;/span>&lt;span style="color:#66d9ef">:&lt;/span> &lt;span style="color:#66d9ef">Optional&lt;/span>&lt;span style="color:#f92672">[&lt;/span>&lt;span style="color:#66d9ef">BufferAndAvailability&lt;/span>&lt;span style="color:#f92672">]&lt;/span> &lt;span style="color:#66d9ef">=&lt;/span> &lt;span style="color:#f92672">{&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> synchronized &lt;span style="color:#f92672">{&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">val&lt;/span> buffer &lt;span style="color:#66d9ef">=&lt;/span> receivedBuffers&lt;span style="color:#f92672">.&lt;/span>poll&lt;span style="color:#f92672">()&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">if&lt;/span> &lt;span style="color:#f92672">(&lt;/span>buffer &lt;span style="color:#f92672">!=&lt;/span> &lt;span style="color:#66d9ef">null&lt;/span>&lt;span style="color:#f92672">)&lt;/span> &lt;span style="color:#f92672">{&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">val&lt;/span> moreAvailable &lt;span style="color:#66d9ef">=&lt;/span> &lt;span style="color:#f92672">!&lt;/span>receivedBuffers&lt;span style="color:#f92672">.&lt;/span>isEmpty &lt;span style="color:#f92672">||&lt;/span> &lt;span style="color:#f92672">!&lt;/span>isReleased
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e">// 增加未通知的信用
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span> unannouncedCredit &lt;span style="color:#f92672">+=&lt;/span> &lt;span style="color:#ae81ff">1&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e">// 如果累积足够信用，发送信用通知
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span> &lt;span style="color:#66d9ef">if&lt;/span> &lt;span style="color:#f92672">(&lt;/span>unannouncedCredit &lt;span style="color:#f92672">&amp;gt;=&lt;/span> networkBuffersPerChannel &lt;span style="color:#f92672">/&lt;/span> &lt;span style="color:#ae81ff">2&lt;/span>&lt;span style="color:#f92672">)&lt;/span> &lt;span style="color:#f92672">{&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> announceCredit&lt;span style="color:#f92672">()&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">}&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">Optional&lt;/span>&lt;span style="color:#f92672">.&lt;/span>of&lt;span style="color:#f92672">(&lt;/span>&lt;span style="color:#66d9ef">new&lt;/span> &lt;span style="color:#a6e22e">BufferAndAvailability&lt;/span>&lt;span style="color:#f92672">(&lt;/span>buffer&lt;span style="color:#f92672">,&lt;/span> moreAvailable&lt;span style="color:#f92672">,&lt;/span> &lt;span style="color:#ae81ff">0&lt;/span>&lt;span style="color:#f92672">))&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">}&lt;/span> &lt;span style="color:#66d9ef">else&lt;/span> &lt;span style="color:#f92672">{&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">Optional&lt;/span>&lt;span style="color:#f92672">.&lt;/span>empty&lt;span style="color:#f92672">()&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">}&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">}&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">}&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e">// 接收缓冲区
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span> &lt;span style="color:#66d9ef">def&lt;/span> onBuffer&lt;span style="color:#f92672">(&lt;/span>buffer&lt;span style="color:#66d9ef">:&lt;/span> &lt;span style="color:#66d9ef">Buffer&lt;/span>&lt;span style="color:#f92672">,&lt;/span> sequenceNumber&lt;span style="color:#66d9ef">:&lt;/span> &lt;span style="color:#66d9ef">Int&lt;/span>&lt;span style="color:#f92672">,&lt;/span> backlog&lt;span style="color:#66d9ef">:&lt;/span> &lt;span style="color:#66d9ef">Int&lt;/span>&lt;span style="color:#f92672">)&lt;/span>&lt;span style="color:#66d9ef">:&lt;/span> &lt;span style="color:#66d9ef">Unit&lt;/span> &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#f92672">{&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> synchronized &lt;span style="color:#f92672">{&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e">// 检查序列号
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span> &lt;span style="color:#66d9ef">if&lt;/span> &lt;span style="color:#f92672">(&lt;/span>sequenceNumber &lt;span style="color:#f92672">==&lt;/span> expectedSequenceNumber&lt;span style="color:#f92672">)&lt;/span> &lt;span style="color:#f92672">{&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> expectedSequenceNumber &lt;span style="color:#f92672">+=&lt;/span> &lt;span style="color:#ae81ff">1&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e">// 添加到接收队列
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span> receivedBuffers&lt;span style="color:#f92672">.&lt;/span>add&lt;span style="color:#f92672">(&lt;/span>buffer&lt;span style="color:#f92672">)&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e">// 通知数据可用
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span> notifyDataAvailable&lt;span style="color:#f92672">()&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e">// 更新积压信息
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span> updateSenderBacklog&lt;span style="color:#f92672">(&lt;/span>backlog&lt;span style="color:#f92672">)&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">}&lt;/span> &lt;span style="color:#66d9ef">else&lt;/span> &lt;span style="color:#f92672">{&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e">// 序列号不匹配，丢弃缓冲区
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span> buffer&lt;span style="color:#f92672">.&lt;/span>recycleBuffer&lt;span style="color:#f92672">()&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">throw&lt;/span> &lt;span style="color:#66d9ef">new&lt;/span> &lt;span style="color:#a6e22e">IllegalStateException&lt;/span>&lt;span style="color:#f92672">(&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e6db74">s&amp;#34;Expected sequence number &lt;/span>&lt;span style="color:#e6db74">$expectedSequenceNumber&lt;/span>&lt;span style="color:#e6db74"> but got &lt;/span>&lt;span style="color:#e6db74">$sequenceNumber&lt;/span>&lt;span style="color:#e6db74">&amp;#34;&lt;/span>&lt;span style="color:#f92672">)&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">}&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">}&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">}&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e">// 通知信用
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span> &lt;span style="color:#66d9ef">private&lt;/span> &lt;span style="color:#66d9ef">def&lt;/span> announceCredit&lt;span style="color:#f92672">()&lt;/span>&lt;span style="color:#66d9ef">:&lt;/span> &lt;span style="color:#66d9ef">Unit&lt;/span> &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#f92672">{&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">if&lt;/span> &lt;span style="color:#f92672">(&lt;/span>unannouncedCredit &lt;span style="color:#f92672">&amp;gt;&lt;/span> &lt;span style="color:#ae81ff">0&lt;/span>&lt;span style="color:#f92672">)&lt;/span> &lt;span style="color:#f92672">{&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">val&lt;/span> creditAnnouncement &lt;span style="color:#66d9ef">=&lt;/span> &lt;span style="color:#66d9ef">new&lt;/span> &lt;span style="color:#a6e22e">NettyMessage&lt;/span>&lt;span style="color:#f92672">.&lt;/span>&lt;span style="color:#a6e22e">AddCredit&lt;/span>&lt;span style="color:#f92672">(&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> partitionId&lt;span style="color:#f92672">,&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> inputChannelId&lt;span style="color:#f92672">,&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> unannouncedCredit&lt;span style="color:#f92672">)&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> connectionManager&lt;span style="color:#f92672">.&lt;/span>getConnection&lt;span style="color:#f92672">(&lt;/span>partitionId&lt;span style="color:#f92672">.&lt;/span>getConnectionId&lt;span style="color:#f92672">)&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">.&lt;/span>writeAndFlush&lt;span style="color:#f92672">(&lt;/span>creditAnnouncement&lt;span style="color:#f92672">)&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> unannouncedCredit &lt;span style="color:#66d9ef">=&lt;/span> &lt;span style="color:#ae81ff">0&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">}&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">}&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e">// 发送初始分区请求
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span> &lt;span style="color:#66d9ef">def&lt;/span> requestSubpartition&lt;span style="color:#f92672">()&lt;/span>&lt;span style="color:#66d9ef">:&lt;/span> &lt;span style="color:#66d9ef">Unit&lt;/span> &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#f92672">{&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">val&lt;/span> partitionRequest &lt;span style="color:#66d9ef">=&lt;/span> &lt;span style="color:#66d9ef">new&lt;/span> &lt;span style="color:#a6e22e">NettyMessage&lt;/span>&lt;span style="color:#f92672">.&lt;/span>&lt;span style="color:#a6e22e">PartitionRequest&lt;/span>&lt;span style="color:#f92672">(&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> partitionId&lt;span style="color:#f92672">,&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> subpartitionIndex&lt;span style="color:#f92672">,&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> inputChannelId&lt;span style="color:#f92672">,&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> networkBuffersPerChannel&lt;span style="color:#f92672">)&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> connectionManager&lt;span style="color:#f92672">.&lt;/span>getConnection&lt;span style="color:#f92672">(&lt;/span>partitionId&lt;span style="color:#f92672">.&lt;/span>getConnectionId&lt;span style="color:#f92672">)&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">.&lt;/span>writeAndFlush&lt;span style="color:#f92672">(&lt;/span>partitionRequest&lt;span style="color:#f92672">)&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">}&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e">// 更新发送方积压
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span> &lt;span style="color:#66d9ef">private&lt;/span> &lt;span style="color:#66d9ef">def&lt;/span> updateSenderBacklog&lt;span style="color:#f92672">(&lt;/span>backlog&lt;span style="color:#66d9ef">:&lt;/span> &lt;span style="color:#66d9ef">Int&lt;/span>&lt;span style="color:#f92672">)&lt;/span>&lt;span style="color:#66d9ef">:&lt;/span> &lt;span style="color:#66d9ef">Unit&lt;/span> &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#f92672">{&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e">// 基于积压调整信用策略
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span> &lt;span style="color:#66d9ef">val&lt;/span> creditToAnnounce &lt;span style="color:#66d9ef">=&lt;/span> &lt;span style="color:#66d9ef">if&lt;/span> &lt;span style="color:#f92672">(&lt;/span>backlog &lt;span style="color:#f92672">&amp;gt;&lt;/span> networkBuffersPerChannel &lt;span style="color:#f92672">*&lt;/span> &lt;span style="color:#ae81ff">2&lt;/span>&lt;span style="color:#f92672">)&lt;/span> &lt;span style="color:#f92672">{&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e">// 高积压，减少信用通知频率
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span> networkBuffersPerChannel
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">}&lt;/span> &lt;span style="color:#66d9ef">else&lt;/span> &lt;span style="color:#f92672">{&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e">// 低积压，增加信用通知频率
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span> networkBuffersPerChannel &lt;span style="color:#f92672">/&lt;/span> &lt;span style="color:#ae81ff">4&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">}&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">if&lt;/span> &lt;span style="color:#f92672">(&lt;/span>unannouncedCredit &lt;span style="color:#f92672">&amp;gt;=&lt;/span> creditToAnnounce&lt;span style="color:#f92672">)&lt;/span> &lt;span style="color:#f92672">{&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> announceCredit&lt;span style="color:#f92672">()&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">}&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">}&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f92672">}&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;hr>
&lt;p>这个Flink源码解析文档已经涵盖了核心的架构和源码分析，包括：&lt;/p></description></item></channel></rss>