<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/">
    <channel>
        <title>  Blog</title>
        <link>https://realfuture.ai/blog</link>
        <description>  Blog</description>
        <lastBuildDate>Fri, 27 Jun 2025 00:00:00 GMT</lastBuildDate>
        <docs>https://validator.w3.org/feed/docs/rss2.html</docs>
        <generator>https://github.com/jpmonette/feed</generator>
        <language>en</language>
        <item>
            <title><![CDATA[Flink Catalog，一次建表全局复用]]></title>
            <link>https://realfuture.ai/blog/2025/06/27/</link>
            <guid>https://realfuture.ai/blog/2025/06/27/</guid>
            <pubDate>Fri, 27 Jun 2025 00:00:00 GMT</pubDate>
            <description><![CDATA[Flink Catalog 统一管理数据库、表、视图与函数等元数据，支持在 SQL 和 Table API 中复用数据源结构。]]></description>
            <content:encoded><![CDATA[<div class="theme-admonition theme-admonition-tip admonition_kxJD alert alert--success"><div class="admonitionHeading_JQHl"><span class="admonitionIcon_Nmmf"><svg viewBox="0 0 12 16"><path fill-rule="evenodd" d="M6.5 0C3.48 0 1 2.19 1 5c0 .92.55 2.25 1 3 1.34 2.25 1.78 2.78 2 4v1h5v-1c.22-1.22.66-1.75 2-4 .45-.75 1-2.08 1-3 0-2.81-2.48-5-5.5-5zm3.64 7.48c-.25.44-.47.8-.67 1.11-.86 1.41-1.25 2.06-1.45 3.23-.02.05-.02.11-.02.17H5c0-.06 0-.13-.02-.17-.2-1.17-.59-1.83-1.45-3.23-.2-.31-.42-.67-.67-1.11C2.44 6.78 2 5.65 2 5c0-2.2 2.02-4 4.5-4 1.22 0 2.36.42 3.22 1.19C10.55 2.94 11 3.94 11 5c0 .66-.44 1.78-.86 2.48zM4 14h5c-.23 1.14-1.3 2-2.5 2s-2.27-.86-2.5-2z"></path></svg></span>温馨提示</div><div class="admonitionContent_i_yp"><p><code>Flink Catalog</code> 是 <code>Flink</code> 提供的一个元数据管理组件，用于统一管理数据库、表、视图、函数等元数据，使得用户可以在 <code>SQL</code> 或 <code>Table API</code> 中像操作数据库一样方便地访问和管理不同数据源的结构信息，实现跨系统的数据互通和一致性操作。</p></div></div>
<p><strong>Awestream</strong> 提供完整的 <code>Flink</code> 元数据管理解决方案，包含如下管理方式：</p>
<ul>
<li><strong>SQL 方式</strong>：支持通过标准 <code>SQL</code> 语句进行元数据操作</li>
<li><strong>可视化方式</strong>：提供友好的图形界面进行元数据管理</li>
</ul>
<!-- -->
<h2 class="anchor anchorWithStickyNavbar_I2Xo" id="streampark-catalog">StreamPark Catalog<a href="https://realfuture.ai/blog/2025/06/27/#streampark-catalog" class="hash-link" aria-label="Direct link to StreamPark Catalog" title="Direct link to StreamPark Catalog">​</a></h2>
<p><strong>Awestream</strong> 内置了 <code>streampark catalog</code> 作为默认元数据存储方案，具有以下特性：</p>
<ul>
<li><strong>多数据库支持</strong>：底层存储支持 <code>H2</code>、<code>MySQL</code> 以及 <code>PostgreSQL</code></li>
<li><strong>业务集成</strong>：与业务数据库绑定，实现统一管理</li>
<li><strong>完整对象支持</strong>：支持 <code>database</code>、<code>table</code> 和 <code>view</code> 三级对象模型</li>
</ul>
<h2 class="anchor anchorWithStickyNavbar_I2Xo" id="可视化方式">可视化方式<a href="https://realfuture.ai/blog/2025/06/27/#%E5%8F%AF%E8%A7%86%E5%8C%96%E6%96%B9%E5%BC%8F" class="hash-link" aria-label="Direct link to 可视化方式" title="Direct link to 可视化方式">​</a></h2>
<p>通过 <strong>Awestream</strong> 控制台，你可以直观地浏览和操作所有元数据对象。</p>
<div data-rmiz=""><div data-rmiz-content="not-found" style="visibility:visible"><img src="https://realfuture.ai/img/blog/2025-06-27/overview.png" alt="overview" style="cursor:pointer"></div></div>
<p>通过图形化界面完成以下操作：</p>
<ul>
<li>创建/修改/删除 database（数据库）</li>
<li>创建/修改/删除 table（表）</li>
<li>创建/修改/删除 view（视图）</li>
<li>查看元数据详情</li>
<li>快速检索元数据对象</li>
<li>……</li>
</ul>
<h2 class="anchor anchorWithStickyNavbar_I2Xo" id="sql-控制台">SQL 控制台<a href="https://realfuture.ai/blog/2025/06/27/#sql-%E6%8E%A7%E5%88%B6%E5%8F%B0" class="hash-link" aria-label="Direct link to SQL 控制台" title="Direct link to SQL 控制台">​</a></h2>
<p>进入作业开发模块，依次点击 <strong>“导航面板” → “SQL 查询”</strong>：</p>
<div data-rmiz=""><div data-rmiz-content="not-found" style="visibility:visible"><img src="https://realfuture.ai/img/blog/2025-06-27/job-draft-console.png" alt="job-draft-console" style="cursor:pointer"></div></div>
<p>从上图可以看出，点击 "<strong>SQL 查询</strong>"  按钮之后，在操作工具栏会固定出现一个 “<strong>SQL Query</strong>” 的页签，中间是你写 <code>Flink SQL</code> 核心的工作区域，当然注释里面也提示了支持的语法。</p>
<h2 class="anchor anchorWithStickyNavbar_I2Xo" id="sql-操作">SQL 操作<a href="https://realfuture.ai/blog/2025/06/27/#sql-%E6%93%8D%E4%BD%9C" class="hash-link" aria-label="Direct link to SQL 操作" title="Direct link to SQL 操作">​</a></h2>
<p>你可以通过 <code>SQL</code> 去管理元数据，<strong>Awestream</strong> 支持所有的 <code>Flink SQL</code> 语法，包括但不限于以下：</p>
<ul>
<li><strong>CREATE</strong>： 创建新的元数据，如：<code>Catalog</code> 、数据库、表、视图等</li>
<li><strong>DROP</strong>：移除已存在的数据结构，如：<code>Catalog</code> 、数据库、表、视图等</li>
<li><strong>ALTER</strong>：修改已存在元数据的属性或定义，如：数据库、表、视图等</li>
<li><strong>SHOW</strong>： 列出 <code>Catalog</code> 、数据库、表、视图或 <code>Function</code> 等信息</li>
<li><strong>DESCRIBE</strong>： 获取表的详细结构信息</li>
<li><strong>SELECT</strong> ：实时数据预览</li>
<li><strong>INSERT</strong> ：实时数据同步</li>
<li>……</li>
</ul>
<h2 class="anchor anchorWithStickyNavbar_I2Xo" id="右键操作">右键操作<a href="https://realfuture.ai/blog/2025/06/27/#%E5%8F%B3%E9%94%AE%E6%93%8D%E4%BD%9C" class="hash-link" aria-label="Direct link to 右键操作" title="Direct link to 右键操作">​</a></h2>
<p>除了通过 SQL 的方式管理元数据，这里还提供了 “<strong>右键元数据树</strong>” 的快捷方式。不同的树节点对应不同的操作：</p>
<ul>
<li><strong>Catalog 节点</strong>：支持 “复制名称” 以及 “插入 <code>DDL</code>” 的操作</li>
<li><strong>Database 节点</strong>：支持 “复制名称” 以及 “插入 <code>DDL</code>” 的操作</li>
<li><strong>Tables 节点</strong>：支持 “刷新” 以及 “插入表” 的操作</li>
<li><strong>Table 节点</strong>：支持 “复制名称” 、 “插入DDL”、“修改属性”以及 “删除表” 的操作</li>
<li><strong>Views 节点</strong>：仅支持 “刷新” 的操作</li>
<li><strong>View 节点</strong>：支持 “复制名称” 、 “插入DDL” 以及 “删除视图” 的操作</li>
</ul>
<h3 class="anchor anchorWithStickyNavbar_I2Xo" id="catalog-管理">Catalog 管理<a href="https://realfuture.ai/blog/2025/06/27/#catalog-%E7%AE%A1%E7%90%86" class="hash-link" aria-label="Direct link to Catalog 管理" title="Direct link to Catalog 管理">​</a></h3>
<p>鼠标移动至元数据树的 <code>Catalog</code> 节点，然后右键，可以看到支持 <strong>复制名称</strong> 以及 <strong>插入 <code>DDL</code></strong> 的操作。</p>
<div data-rmiz=""><div data-rmiz-content="not-found" style="visibility:visible"><img src="https://realfuture.ai/img/blog/2025-06-27/job-draft-right-btn-catalog.png" alt="job-draft-right-btn-catalog" style="cursor:pointer"></div></div>
<p>点击 <strong>插入DDL</strong> 操作后，可以看到把当前选中的 <code>Catalog</code> 节点的 <code>DDL</code> 信息插入到了右侧的工作编辑区，你直接通过修改相关的配置，即可执行并创建 <code>Catalog</code>。</p>
<div data-rmiz=""><div data-rmiz-content="not-found" style="visibility:visible"><img src="https://realfuture.ai/img/blog/2025-06-27/job-draft-right-btn-catalog-create.png" alt="job-draft-right-btn-catalog-create" style="cursor:pointer"></div></div>
<h3 class="anchor anchorWithStickyNavbar_I2Xo" id="database-操作">Database 操作<a href="https://realfuture.ai/blog/2025/06/27/#database-%E6%93%8D%E4%BD%9C" class="hash-link" aria-label="Direct link to Database 操作" title="Direct link to Database 操作">​</a></h3>
<p>鼠标移动至元数据树的 <code>Database</code> 节点，然后右键，可以看到支持 <strong>复制名称</strong> 以及 <strong>插入 <code>DDL</code></strong> 的操作。</p>
<div data-rmiz=""><div data-rmiz-content="not-found" style="visibility:visible"><img src="https://realfuture.ai/img/blog/2025-06-27/job-draft-right-btn-database.png" alt="job-draft-right-btn-database" style="cursor:pointer"></div></div>
<p>点击 <strong>插入DDL</strong> 操作后，可以看到把当前选中的 <code>Database</code> 节点的 <code>DDL</code> 信息插入到了右侧的工作编辑区，你直接通过修改相关的配置，即可执行并创建 <code>Database</code>。</p>
<div data-rmiz=""><div data-rmiz-content="not-found" style="visibility:visible"><img src="https://realfuture.ai/img/blog/2025-06-27/job-draft-right-btn-database-create.png" alt="job-draft-right-btn-database-create" style="cursor:pointer"></div></div>
<h3 class="anchor anchorWithStickyNavbar_I2Xo" id="tables-操作">Tables 操作<a href="https://realfuture.ai/blog/2025/06/27/#tables-%E6%93%8D%E4%BD%9C" class="hash-link" aria-label="Direct link to Tables 操作" title="Direct link to Tables 操作">​</a></h3>
<p>鼠标移动至元数据树的 <code>Tables</code> 节点，然后右键，可以看到支持 <strong>刷新</strong> 以及 <strong>插入表</strong> 的操作，可以通过选择连接器来快速创建表。</p>
<div data-rmiz=""><div data-rmiz-content="not-found" style="visibility:visible"><img src="https://realfuture.ai/img/blog/2025-06-27/job-draft-right-btn-tables.png" alt="job-draft-right-btn-tables" style="cursor:pointer"></div></div>
<p>例如这里选择了 <code>jdbc</code> 连接器，那么在右侧的工作编辑区域，会根据我们选择的连接器，自动填充对应的 <strong>建表模板</strong>，如下图所示：</p>
<div data-rmiz=""><div data-rmiz-content="not-found" style="visibility:visible"><img src="https://realfuture.ai/img/blog/2025-06-27/job-draft-right-btn-tables-create.png" alt="job-draft-right-btn-tables-create" style="cursor:pointer"></div></div>
<h3 class="anchor anchorWithStickyNavbar_I2Xo" id="table-操作">Table 操作<a href="https://realfuture.ai/blog/2025/06/27/#table-%E6%93%8D%E4%BD%9C" class="hash-link" aria-label="Direct link to Table 操作" title="Direct link to Table 操作">​</a></h3>
<p>鼠标移动至元数据树的 <code>Table</code> 节点，然后右键，可以看到支持 <strong>复制名称</strong> 、 <strong>插入DDL</strong>、<strong>修改属性</strong>以及 <strong>删除表</strong> 的操作。</p>
<div data-rmiz=""><div data-rmiz-content="not-found" style="visibility:visible"><img src="https://realfuture.ai/img/blog/2025-06-27/job-draft-right-btn-table.png" alt="job-draft-right-btn-table" style="cursor:pointer"></div></div>
<p>如果点击复制名称，会直接复制对应的表名。点击删除表，会自动把表删除。当然也可以插入 <code>DDL</code>，在右侧的工作编辑区会看见对应表的 <code>DDL</code> 内容，如下图：</p>
<div data-rmiz=""><div data-rmiz-content="not-found" style="visibility:visible"><img src="https://realfuture.ai/img/blog/2025-06-27/job-draft-right-btn-table-ddl.png" alt="job-draft-right-btn-table-ddl" style="cursor:pointer"></div></div>
<p>当然也可以右键修改表的属性，如下图：</p>
<div data-rmiz=""><div data-rmiz-content="not-found" style="visibility:visible"><img src="https://realfuture.ai/img/blog/2025-06-27/job-draft-right-btn-table-alter.png" alt="job-draft-right-btn-table-alter" style="cursor:pointer"></div></div>
<h3 class="anchor anchorWithStickyNavbar_I2Xo" id="views-操作">Views 操作<a href="https://realfuture.ai/blog/2025/06/27/#views-%E6%93%8D%E4%BD%9C" class="hash-link" aria-label="Direct link to Views 操作" title="Direct link to Views 操作">​</a></h3>
<p>鼠标移动至元数据树的 <code>Views</code> 节点，然后右键，可以看到仅支持 <strong>刷新</strong> 的操作。</p>
<div data-rmiz=""><div data-rmiz-content="not-found" style="visibility:visible"><img src="https://realfuture.ai/img/blog/2025-06-27/job-draft-right-btn-views.png" alt="job-draft-right-btn-views" style="cursor:pointer"></div></div>
<h3 class="anchor anchorWithStickyNavbar_I2Xo" id="view-操作">View 操作<a href="https://realfuture.ai/blog/2025/06/27/#view-%E6%93%8D%E4%BD%9C" class="hash-link" aria-label="Direct link to View 操作" title="Direct link to View 操作">​</a></h3>
<p>鼠标移动至元数据树的 <code>View</code> 节点，然后右键，可以看到支持 <strong>复制名称</strong> 、 <strong>插入DDL</strong> 以及 <strong>删除视图</strong> 的操作。</p>
<div data-rmiz=""><div data-rmiz-content="not-found" style="visibility:visible"><img src="https://realfuture.ai/img/blog/2025-06-27/job-draft-right-btn-view.png" alt="job-draft-right-btn-view" style="cursor:pointer"></div></div>
<p>如果点击复制名称，会直接复制对应的表名。点击删除表，会自动把表删除。当然也可以插入 <code>DDL</code>，在右侧的工作编辑区会看见对应表的 <code>DDL</code> 内容，如下图：</p>
<div data-rmiz=""><div data-rmiz-content="not-found" style="visibility:visible"><img src="https://realfuture.ai/img/blog/2025-06-27/job-draft-right-btn-view-ddl.png" alt="job-draft-right-btn-view-ddl" style="cursor:pointer"></div></div>]]></content:encoded>
            <category>Realfuture</category>
            <category>Engineering</category>
        </item>
        <item>
            <title><![CDATA[Flink SQL 开发 IDE：提升作业开发与调试效率]]></title>
            <link>https://realfuture.ai/blog/2025/06/26/</link>
            <guid>https://realfuture.ai/blog/2025/06/26/</guid>
            <pubDate>Thu, 26 Jun 2025 00:00:00 GMT</pubDate>
            <description><![CDATA[Awestream 的 Flink SQL 开发 IDE 集成作业配置、校验、调试与结果预览，帮助团队缩短开发周期。]]></description>
            <content:encoded><![CDATA[<blockquote>
<p>作业开发调试工具是 <strong>Awestream</strong> 技术团队花费大量时间打磨出的模块，它的出现能让您的团队如虎添翼，事半功倍。</p>
<p><strong>Awestream</strong> 内置了功能完善的作业开发与调试工具，可快速、高效地完成作业配置。</p>
<p><strong>Awestream</strong> 作业开发调试工具能够连通元数据、 <code>UDF</code> 管理、 <code>JAR</code> 资源和项目资源，便于用户在作业开发配置中快捷查看或使用。</p>
<p><strong>Awestream</strong> 作业开发调试工具支持实时保存、编辑器字号与行高调整、代码折叠和自动换行等常见操作，满足不同用户的使用习惯。</p>
</blockquote>
<!-- -->
<h2 class="anchor anchorWithStickyNavbar_I2Xo" id="1-落地页">1. 落地页<a href="https://realfuture.ai/blog/2025/06/26/#1-%E8%90%BD%E5%9C%B0%E9%A1%B5" class="hash-link" aria-label="Direct link to 1. 落地页" title="Direct link to 1. 落地页">​</a></h2>
<p>当用户进入作业开发页面时会出现一个落地页，落地页中列举出了关于 <code>SQL</code> 的一些常见语法规则，并且提供了一个新建作业草稿的按钮。</p>
<div data-rmiz=""><div data-rmiz-content="not-found" style="visibility:visible"><img src="https://realfuture.ai/img/blog/2025-06-26/welcome.png" alt="welcome" style="cursor:pointer"></div></div>
<p>用户点击新建作业草稿的按钮后会出现一个弹窗，可根据弹窗信息创建不同的作业。</p>
<div class="theme-admonition theme-admonition-warning admonition_kxJD alert alert--warning"><div class="admonitionHeading_JQHl"><span class="admonitionIcon_Nmmf"><svg viewBox="0 0 16 16"><path fill-rule="evenodd" d="M8.893 1.5c-.183-.31-.52-.5-.887-.5s-.703.19-.886.5L.138 13.499a.98.98 0 0 0 0 1.001c.193.31.53.501.886.501h13.964c.367 0 .704-.19.877-.5a1.03 1.03 0 0 0 .01-1.002L8.893 1.5zm.133 11.497H6.987v-2.003h2.039v2.003zm0-3.004H6.987V5.987h2.039v4.006z"></path></svg></span>注意</div><div class="admonitionContent_i_yp"><ul>
<li>
<p>需要注意的是，不同作业类型的配置略有不同，<strong>数据开发</strong> 中可以创建 <code>SQL</code> 和 <code>JAR</code> 作业，<strong>数据集成</strong> 只能创建 <code>CDC</code> 作业。</p>
</li>
<li>
<p><strong>存储位置</strong> 是作业目标归属的文件夹，文件夹最大层级为四层，可在 <a href="https://realfuture.ai/blog/2025/06/26/#23-%E4%BD%9C%E4%B8%9A%E8%8D%89%E7%A8%BF%E9%9D%A2%E6%9D%BF">作业草稿面板</a> 中查看更多信息。</p>
</li>
<li>
<p><strong>数据集成</strong> 中的 <strong>执行模式</strong> 只能选择流作业，不能选择批作业。</p>
</li>
</ul></div></div>
<div data-rmiz=""><div data-rmiz-content="not-found" style="visibility:visible"><img src="https://realfuture.ai/img/blog/2025-06-26/create-job-modal.png" alt="create-job-modal" style="cursor:pointer"></div></div>
<h2 class="anchor anchorWithStickyNavbar_I2Xo" id="2-面板">2. 面板<a href="https://realfuture.ai/blog/2025/06/26/#2-%E9%9D%A2%E6%9D%BF" class="hash-link" aria-label="Direct link to 2. 面板" title="Direct link to 2. 面板">​</a></h2>
<p>面板是作业开发调试工具中每个模块的统称，面板可以通过拖拽改变不同面板之间大小的比例。</p>
<div class="theme-admonition theme-admonition-tip admonition_kxJD alert alert--success"><div class="admonitionHeading_JQHl"><span class="admonitionIcon_Nmmf"><svg viewBox="0 0 12 16"><path fill-rule="evenodd" d="M6.5 0C3.48 0 1 2.19 1 5c0 .92.55 2.25 1 3 1.34 2.25 1.78 2.78 2 4v1h5v-1c.22-1.22.66-1.75 2-4 .45-.75 1-2.08 1-3 0-2.81-2.48-5-5.5-5zm3.64 7.48c-.25.44-.47.8-.67 1.11-.86 1.41-1.25 2.06-1.45 3.23-.02.05-.02.11-.02.17H5c0-.06 0-.13-.02-.17-.2-1.17-.59-1.83-1.45-3.23-.2-.31-.42-.67-.67-1.11C2.44 6.78 2 5.65 2 5c0-2.2 2.02-4 4.5-4 1.22 0 2.36.42 3.22 1.19C10.55 2.94 11 3.94 11 5c0 .66-.44 1.78-.86 2.48zM4 14h5c-.23 1.14-1.3 2-2.5 2s-2.27-.86-2.5-2z"></path></svg></span>提示</div><div class="admonitionContent_i_yp"><p>可改变大小比例的面板有作业草稿、元数据、 <code>UDF</code> 管理、  <code>JAR</code> 相关的资源面板以及开发面板、结果面板和属性面板，同时可改变大小比例的面板在鼠标移动到分割线时会有蓝色高亮并且支持最小化隐藏。</p></div></div>
<div data-rmiz=""><div data-rmiz-content="not-found" style="visibility:visible"><img src="https://realfuture.ai/img/blog/2025-06-26/pane-highlight.png" alt="pane-highlight" style="cursor:pointer"></div></div>
<p>面板承载了作业开发调试工具的基本交互结构，它包含栏目面板、资源面板（包含操作栏）、开发面板（包含标签栏、操作栏、配置栏、抽屉面板和开发区域）、结果面板（包含操作栏）、属性面板（包含操作栏）和底部面板。</p>
<div data-rmiz=""><div data-rmiz-content="not-found" style="visibility:visible"><img src="https://realfuture.ai/img/blog/2025-06-26/pane.png" alt="pane" style="cursor:pointer"></div></div>
<h3 class="anchor anchorWithStickyNavbar_I2Xo" id="21-栏目面板">2.1 栏目面板<a href="https://realfuture.ai/blog/2025/06/26/#21-%E6%A0%8F%E7%9B%AE%E9%9D%A2%E6%9D%BF" class="hash-link" aria-label="Direct link to 2.1 栏目面板" title="Direct link to 2.1 栏目面板">​</a></h3>
<p>栏目面板中的按钮从上到下依次对应作业草稿、元数据、<code>SQL</code> 查询作业、更多（<code>UDF</code> 管理和 <code>JAR</code> 资源）、运行结果和属性。点击按钮可打开或关闭相应的面板或作业。</p>
<h3 class="anchor anchorWithStickyNavbar_I2Xo" id="22-资源面板的操作栏">2.2 资源面板的操作栏<a href="https://realfuture.ai/blog/2025/06/26/#22-%E8%B5%84%E6%BA%90%E9%9D%A2%E6%9D%BF%E7%9A%84%E6%93%8D%E4%BD%9C%E6%A0%8F" class="hash-link" aria-label="Direct link to 2.2 资源面板的操作栏" title="Direct link to 2.2 资源面板的操作栏">​</a></h3>
<table><thead><tr><th>功能</th><th>作业草稿面板</th><th>元数据面板</th><th>UDF 管理面板</th><th>JAR 资源面板</th></tr></thead><tbody><tr><td>打开或关闭模糊搜索（搜索内容会在资源树中高亮）</td><td>✓</td><td>✓</td><td></td><td>✓</td></tr><tr><td>新建草稿</td><td>✓</td><td></td><td></td><td></td></tr><tr><td>注册函数</td><td></td><td></td><td>✓</td><td></td></tr><tr><td>添加 <code>JAR</code> 资源（跳转到添加资源页面）</td><td></td><td></td><td></td><td>✓</td></tr><tr><td>刷新（重新加载树资源）</td><td>✓</td><td>✓</td><td>✓</td><td>✓</td></tr><tr><td>全部折叠（只展示第一级资源）</td><td>✓</td><td>✓</td><td></td><td>✓</td></tr><tr><td>定位（高亮当前作业在树中的位置）</td><td>✓</td><td></td><td></td><td></td></tr><tr><td>显示或不显示类型（是否显示元数据类型）</td><td></td><td>✓</td><td></td><td></td></tr><tr><td>最小化（关闭当前面板）</td><td>✓</td><td>✓</td><td>✓</td><td>✓</td></tr></tbody></table>
<h4 class="anchor anchorWithStickyNavbar_I2Xo" id="221-模糊搜索">2.2.1 模糊搜索<a href="https://realfuture.ai/blog/2025/06/26/#221-%E6%A8%A1%E7%B3%8A%E6%90%9C%E7%B4%A2" class="hash-link" aria-label="Direct link to 2.2.1 模糊搜索" title="Direct link to 2.2.1 模糊搜索">​</a></h4>
<p>模糊搜索会将搜索的内容进行匹配和高亮，便于用户快速定位。</p>
<div data-rmiz=""><div data-rmiz-content="not-found" style="visibility:visible"><img src="https://realfuture.ai/img/blog/2025-06-26/search.png" alt="search" style="cursor:pointer"></div></div>
<h3 class="anchor anchorWithStickyNavbar_I2Xo" id="23-作业草稿面板">2.3 作业草稿面板<a href="https://realfuture.ai/blog/2025/06/26/#23-%E4%BD%9C%E4%B8%9A%E8%8D%89%E7%A8%BF%E9%9D%A2%E6%9D%BF" class="hash-link" aria-label="Direct link to 2.3 作业草稿面板" title="Direct link to 2.3 作业草稿面板">​</a></h3>
<p>作业草稿面板是进入作业开发页面后默认打开的，它会有一个默认展开的文件夹（<code>default</code>），它是一个不可被重命名、删除或移动的文件夹，它只允许新建作业草稿或新建文件夹。</p>
<div data-rmiz=""><div data-rmiz-content="not-found" style="visibility:visible"><img src="https://realfuture.ai/img/blog/2025-06-26/draft-pane.png" alt="draft-pane" style="cursor:pointer"></div></div>
<p>作业草稿面板除 <code>default</code> 文件夹以外的文件夹和作业草稿支持拖拽改变存储位置。</p>
<p>作业草稿面板的文件夹和作业草稿支持右键菜单的操作。其中针对文件夹的操作有新建文件夹、新建草稿、重命名和删除文件夹，针对作业草稿的操作有重命名和删除作业草稿。</p>
<p>作业草稿面板可通过双击的形式打开作业草稿或展开收起文件夹，当双击作业草稿时，则会进入作业草稿的编辑状态（文件夹的展开和收起也可使用文件夹图标前的折叠图标进行控制）。</p>
<p>通过右键点击文件夹的新建作业草稿后，会出现新建作业弹窗，弹窗的存储位置默认值为当前点击的文件夹。</p>
<p>出于一定因素考虑，文件夹最大层级为四层，当右键点击第四层文件夹时则不再会出现新建文件夹的选项，同样如果拖拽文件夹到第四层文件夹时也会出现错误提示。</p>
<p>作业是否上线可以通过作业树中作业草稿名称的高亮进行判断，如果是灰色作业类型图标和灰色作业草稿名称则表示当前作业没有上线，没有上线的作业无法在作业运维中查看。</p>
<h3 class="anchor anchorWithStickyNavbar_I2Xo" id="24-元数据面板">2.4 元数据面板<a href="https://realfuture.ai/blog/2025/06/26/#24-%E5%85%83%E6%95%B0%E6%8D%AE%E9%9D%A2%E6%9D%BF" class="hash-link" aria-label="Direct link to 2.4 元数据面板" title="Direct link to 2.4 元数据面板">​</a></h3>
<p>元数据面板不是作业开发工具默认打开的资源面板，考虑到数据体量元数据面板默认会打开第一个数据源的第一层。</p>
<div data-rmiz=""><div data-rmiz-content="not-found" style="visibility:visible"><img src="https://realfuture.ai/img/blog/2025-06-26/metadata-pane.png" alt="metadata-pane" style="cursor:pointer"></div></div>
<p>元数据面板的节点不支持拖拽。</p>
<p>元数据面板总共分为四层，分别是 <code>Catalog</code> 、 <code>Database</code> 、 <code>Tables 和 Views</code> 、 <code>Table 和 View</code> 。其中 <code>Catalog</code> 、 <code>Database</code> 、 <code>Table</code> 和 <code>View</code> 节点在鼠标点击后会弹出 <a href="https://realfuture.ai/blog/2025/06/26/#28-%E5%B1%9E%E6%80%A7%E9%9D%A2%E6%9D%BF">属性面板</a> ，用户可通过属性面板进一步查看元数据的信息。</p>
<div data-rmiz=""><div data-rmiz-content="not-found" style="visibility:visible"><img src="https://realfuture.ai/img/blog/2025-06-26/metadata-attr.png" alt="metadata-attr" style="cursor:pointer"></div></div>
<p>元数据面板的节点支持右键菜单的操作，具体如下：</p>
<div data-rmiz=""><div data-rmiz-content="not-found" style="visibility:visible"><img src="https://realfuture.ai/img/blog/2025-06-26/metadata-content-menu.png" alt="metadata-content-menu" style="cursor:pointer"></div></div>
<ul>
<li><code>Catalog</code> 和 <code>Database</code> 的操作有复制名称和插入 <code>DDL</code>。</li>
<li><code>Tables</code> 的操作有刷新和插入表。</li>
<li><code>Views</code> 的操作有刷新。</li>
<li><code>Table</code> 的操作有复制名称、插入 <code>DDL</code> 、修改属性和删除表。</li>
<li><code>View</code> 的操作有复制名称、插入 <code>DDL</code> 和删除视图。</li>
</ul>
<div class="theme-admonition theme-admonition-warning admonition_kxJD alert alert--warning"><div class="admonitionHeading_JQHl"><span class="admonitionIcon_Nmmf"><svg viewBox="0 0 16 16"><path fill-rule="evenodd" d="M8.893 1.5c-.183-.31-.52-.5-.887-.5s-.703.19-.886.5L.138 13.499a.98.98 0 0 0 0 1.001c.193.31.53.501.886.501h13.964c.367 0 .704-.19.877-.5a1.03 1.03 0 0 0 .01-1.002L8.893 1.5zm.133 11.497H6.987v-2.003h2.039v2.003zm0-3.004H6.987V5.987h2.039v4.006z"></path></svg></span>注意</div><div class="admonitionContent_i_yp"><p>需要注意的是插入 <code>DDL</code> 和修改属性的操作在没有打开 <code>SQL</code> 查询或 <code>SQL</code> 作业时不会出现在右键菜单。</p></div></div>
<h3 class="anchor anchorWithStickyNavbar_I2Xo" id="25-udf-管理面板">2.5 UDF 管理面板<a href="https://realfuture.ai/blog/2025/06/26/#25-udf-%E7%AE%A1%E7%90%86%E9%9D%A2%E6%9D%BF" class="hash-link" aria-label="Direct link to 2.5 UDF 管理面板" title="Direct link to 2.5 UDF 管理面板">​</a></h3>
<p><code>UDF</code> 管理面板的节点不支持拖拽。</p>
<p><code>UDF</code> 管理面板的文件夹和函数支持右键菜单的操作。</p>
<p>针对文件夹的操作有管理，点击后会出现函数管理弹窗，通过弹窗可以进行当前文件夹下函数的批量删除操作。</p>
<div data-rmiz=""><div data-rmiz-content="not-found" style="visibility:visible"><img src="https://realfuture.ai/img/blog/2025-06-26/function-manage.png" alt="function-manage" style="cursor:pointer"></div></div>
<p>针对函数的操作有复制名称和删除函数。</p>
<p>函数注册可点击 <code>UDF</code> 管理面板中操作栏的加号图标后在出现的弹窗中进行选择。</p>
<div data-rmiz=""><div data-rmiz-content="not-found" style="visibility:visible"><img src="https://realfuture.ai/img/blog/2025-06-26/register-function.png" alt="register-function" style="cursor:pointer"></div></div>
<h3 class="anchor anchorWithStickyNavbar_I2Xo" id="26-jar-资源面板">2.6 JAR 资源面板<a href="https://realfuture.ai/blog/2025/06/26/#26-jar-%E8%B5%84%E6%BA%90%E9%9D%A2%E6%9D%BF" class="hash-link" aria-label="Direct link to 2.6 JAR 资源面板" title="Direct link to 2.6 JAR 资源面板">​</a></h3>
<p><code>JAR</code> 资源面板的节点不支持右键菜单的操作。</p>
<p><code>JAR</code> 资源面板默认展开资源文件夹中的 <code>Flink App</code> 目录。</p>
<div data-rmiz=""><div data-rmiz-content="not-found" style="visibility:visible"><img src="https://realfuture.ai/img/blog/2025-06-26/jar-pane.png" alt="jar-pane" style="cursor:pointer"></div></div>
<p><code>Flink App</code> 、<code>Catalog</code> 、<code>Connector</code> 、<code>Function</code> 、<code>Format</code> 和其它目录下的资源在 <code>JAR</code> 作业下可以进行拖拽，拖拽的初衷是便于用户在 <code>JAR</code> 作业中配置资源。</p>
<div data-rmiz=""><div data-rmiz-content="not-found" style="visibility:visible"><img src="https://realfuture.ai/img/blog/2025-06-26/jar-drag.png" alt="jar-drag" style="cursor:pointer"></div></div>
<h3 class="anchor anchorWithStickyNavbar_I2Xo" id="27-结果面板">2.7 结果面板<a href="https://realfuture.ai/blog/2025/06/26/#27-%E7%BB%93%E6%9E%9C%E9%9D%A2%E6%9D%BF" class="hash-link" aria-label="Direct link to 2.7 结果面板" title="Direct link to 2.7 结果面板">​</a></h3>
<p>结果面板是执行作业校验、运行和发布后自动弹起的一个面板，它承载了校验失败、校验成功、运行失败、预览结果和发布失败的信息。</p>
<div class="theme-admonition theme-admonition-warning admonition_kxJD alert alert--warning"><div class="admonitionHeading_JQHl"><span class="admonitionIcon_Nmmf"><svg viewBox="0 0 16 16"><path fill-rule="evenodd" d="M8.893 1.5c-.183-.31-.52-.5-.887-.5s-.703.19-.886.5L.138 13.499a.98.98 0 0 0 0 1.001c.193.31.53.501.886.501h13.964c.367 0 .704-.19.877-.5a1.03 1.03 0 0 0 .01-1.002L8.893 1.5zm.133 11.497H6.987v-2.003h2.039v2.003zm0-3.004H6.987V5.987h2.039v4.006z"></path></svg></span>注意</div><div class="admonitionContent_i_yp"><ul>
<li>
<p>结果面板是全局唯一的，就是说一个作业执行操作后的结果会被下一次执行操作覆盖。</p>
</li>
<li>
<p>进入作业开发调试工具后，如果没有执行作业对应的相关操作，直接点击栏目面板的结果面板按钮时，打开的结果面板内容为空。</p>
</li>
<li>
<p>结果面板中的数据即使用户在最小化关闭结果面板后，依然会被保留，直至下一次执行结果的出现，才会被替换。</p>
</li>
</ul></div></div>
<h3 class="anchor anchorWithStickyNavbar_I2Xo" id="28-属性面板">2.8 属性面板<a href="https://realfuture.ai/blog/2025/06/26/#28-%E5%B1%9E%E6%80%A7%E9%9D%A2%E6%9D%BF" class="hash-link" aria-label="Direct link to 2.8 属性面板" title="Direct link to 2.8 属性面板">​</a></h3>
<p>属性面板是在点击元数据面板中的 <code>Catalog</code> 、 <code>Database</code> 、 <code>Table</code> 和 <code>View</code> 的节点时自动弹起的面板。</p>
<div class="theme-admonition theme-admonition-warning admonition_kxJD alert alert--warning"><div class="admonitionHeading_JQHl"><span class="admonitionIcon_Nmmf"><svg viewBox="0 0 16 16"><path fill-rule="evenodd" d="M8.893 1.5c-.183-.31-.52-.5-.887-.5s-.703.19-.886.5L.138 13.499a.98.98 0 0 0 0 1.001c.193.31.53.501.886.501h13.964c.367 0 .704-.19.877-.5a1.03 1.03 0 0 0 .01-1.002L8.893 1.5zm.133 11.497H6.987v-2.003h2.039v2.003zm0-3.004H6.987V5.987h2.039v4.006z"></path></svg></span>注意</div><div class="admonitionContent_i_yp"><ul>
<li>
<p>属性面板是全局唯一的，只有在点击新的节点后，才会更新属性面板的数据，并且属性面板中的数据在用户最小化关闭面板后依然会被保留。</p>
</li>
<li>
<p>进入作业开发调试工具后，如果没有点击元数据面板中的节点，即使打开的结果面板内容也为空。</p>
</li>
</ul></div></div>
<h3 class="anchor anchorWithStickyNavbar_I2Xo" id="29-底部面板">2.9 底部面板<a href="https://realfuture.ai/blog/2025/06/26/#29-%E5%BA%95%E9%83%A8%E9%9D%A2%E6%9D%BF" class="hash-link" aria-label="Direct link to 2.9 底部面板" title="Direct link to 2.9 底部面板">​</a></h3>
<p>底部面板包含的功能有路径、保存状态、最后保存时间和设置。</p>
<p>当用户处在落地页时路径显示为作业草稿，当用户打开 <code>SQL</code> 查询时，则会显示为 <code>SQL</code> 查询，当用户打开其它作业时则会展示改作业在作业草稿面板中所处的层级路径。</p>
<p>最后保存时间在 <code>SQL</code> 查询时不会出现，设置功能在 <code>JAR</code> 作业时不会出现。</p>
<p>设置功能可以更改编辑器的字体大小、行高、是否开启代码折叠和是否能够自动换行。</p>
<div data-rmiz=""><div data-rmiz-content="not-found" style="visibility:visible"><img src="https://realfuture.ai/img/blog/2025-06-26/bottom-pane-setting.png" alt="bottom-pane-setting" style="cursor:pointer"></div></div>
<p>作业开发调试工具支持作业配置的实时保存，在用户更改作业时，都会触发保存功能，自动保存成功后会自动更新最后保存时间。</p>
<div class="theme-admonition theme-admonition-tip admonition_kxJD alert alert--success"><div class="admonitionHeading_JQHl"><span class="admonitionIcon_Nmmf"><svg viewBox="0 0 12 16"><path fill-rule="evenodd" d="M6.5 0C3.48 0 1 2.19 1 5c0 .92.55 2.25 1 3 1.34 2.25 1.78 2.78 2 4v1h5v-1c.22-1.22.66-1.75 2-4 .45-.75 1-2.08 1-3 0-2.81-2.48-5-5.5-5zm3.64 7.48c-.25.44-.47.8-.67 1.11-.86 1.41-1.25 2.06-1.45 3.23-.02.05-.02.11-.02.17H5c0-.06 0-.13-.02-.17-.2-1.17-.59-1.83-1.45-3.23-.2-.31-.42-.67-.67-1.11C2.44 6.78 2 5.65 2 5c0-2.2 2.02-4 4.5-4 1.22 0 2.36.42 3.22 1.19C10.55 2.94 11 3.94 11 5c0 .66-.44 1.78-.86 2.48zM4 14h5c-.23 1.14-1.3 2-2.5 2s-2.27-.86-2.5-2z"></path></svg></span>提示</div><div class="admonitionContent_i_yp"><p>作业未保存时会在底部面板路径后面和作业面板标签栏中进行标红。</p></div></div>
<div data-rmiz=""><div data-rmiz-content="not-found" style="visibility:visible"><img src="https://realfuture.ai/img/blog/2025-06-26/bottom-pane-unsave.png" alt="bottom-pane-unsave" style="cursor:pointer"></div></div>
<h3 class="anchor anchorWithStickyNavbar_I2Xo" id="210-开发面板">2.10 开发面板<a href="https://realfuture.ai/blog/2025/06/26/#210-%E5%BC%80%E5%8F%91%E9%9D%A2%E6%9D%BF" class="hash-link" aria-label="Direct link to 2.10 开发面板" title="Direct link to 2.10 开发面板">​</a></h3>
<p>不同作业类型的开发面板有所不同，但是每种作业类型都有开发区域、标签栏、操作栏和配置栏。</p>
<h4 class="anchor anchorWithStickyNavbar_I2Xo" id="2101-开发区域">2.10.1 开发区域<a href="https://realfuture.ai/blog/2025/06/26/#2101-%E5%BC%80%E5%8F%91%E5%8C%BA%E5%9F%9F" class="hash-link" aria-label="Direct link to 2.10.1 开发区域" title="Direct link to 2.10.1 开发区域">​</a></h4>
<p><a href="https://realfuture.ai/blog/2025/06/26/#3-%E5%BC%80%E5%8F%91%E5%8C%BA%E5%9F%9F">开发区域</a> 总共有三种，分别是 <code>JAR</code> 作业的表单、 <code>CDC</code> 作业的 <code>YAML</code> 编辑器和 <code>SQL</code> 查询以及 <code>SQL</code> 作业的 <code>SQL</code> 编辑器。</p>
<h4 class="anchor anchorWithStickyNavbar_I2Xo" id="2102-标签栏">2.10.2 标签栏<a href="https://realfuture.ai/blog/2025/06/26/#2102-%E6%A0%87%E7%AD%BE%E6%A0%8F" class="hash-link" aria-label="Direct link to 2.10.2 标签栏" title="Direct link to 2.10.2 标签栏">​</a></h4>
<p>标签栏是用户当前打开作业的名称集合，它与我们常见编辑的文件标签栏同质，用户可以点击标签栏中的关闭按钮关闭当前作业。</p>
<div class="theme-admonition theme-admonition-tip admonition_kxJD alert alert--success"><div class="admonitionHeading_JQHl"><span class="admonitionIcon_Nmmf"><svg viewBox="0 0 12 16"><path fill-rule="evenodd" d="M6.5 0C3.48 0 1 2.19 1 5c0 .92.55 2.25 1 3 1.34 2.25 1.78 2.78 2 4v1h5v-1c.22-1.22.66-1.75 2-4 .45-.75 1-2.08 1-3 0-2.81-2.48-5-5.5-5zm3.64 7.48c-.25.44-.47.8-.67 1.11-.86 1.41-1.25 2.06-1.45 3.23-.02.05-.02.11-.02.17H5c0-.06 0-.13-.02-.17-.2-1.17-.59-1.83-1.45-3.23-.2-.31-.42-.67-.67-1.11C2.44 6.78 2 5.65 2 5c0-2.2 2.02-4 4.5-4 1.22 0 2.36.42 3.22 1.19C10.55 2.94 11 3.94 11 5c0 .66-.44 1.78-.86 2.48zM4 14h5c-.23 1.14-1.3 2-2.5 2s-2.27-.86-2.5-2z"></path></svg></span>提示</div><div class="admonitionContent_i_yp"><p><code>SQL</code> 查询作业永远在标签栏的第一个位置出现，其它作业按照打开顺序依次排开。</p></div></div>
<h4 class="anchor anchorWithStickyNavbar_I2Xo" id="2103-操作栏">2.10.3 操作栏<a href="https://realfuture.ai/blog/2025/06/26/#2103-%E6%93%8D%E4%BD%9C%E6%A0%8F" class="hash-link" aria-label="Direct link to 2.10.3 操作栏" title="Direct link to 2.10.3 操作栏">​</a></h4>
<table><thead><tr><th>功能</th><th>SQL 预览作业</th><th>SQL 作业</th><th>CDC 作业</th><th>JAR 作业</th></tr></thead><tbody><tr><td><a href="https://realfuture.ai/blog/2025/06/26/#41-%E4%BD%9C%E4%B8%9A%E5%8F%91%E5%B8%83">作业发布</a></td><td></td><td>✓</td><td>✓</td><td>✓</td></tr><tr><td><a href="https://realfuture.ai/blog/2025/06/26/#41-%E4%BD%9C%E4%B8%9A%E5%8F%91%E5%B8%83">作业发布</a> -&gt; Pipeline 详情（作业点击发布后的详细信息）</td><td></td><td>✓</td><td>✓</td><td>✓</td></tr><tr><td>Flink 环境 -&gt; Flink 版本</td><td>✓</td><td>✓</td><td>✓</td><td>✓</td></tr><tr><td>Flink 环境 -&gt; 部署模式</td><td>✓</td><td>✓</td><td>✓</td><td>✓</td></tr><tr><td>Flink 环境 -&gt; Flink 集群</td><td>✓</td><td>✓</td><td>✓</td><td>✓</td></tr><tr><td>Catalog</td><td>✓</td><td>✓</td><td></td><td></td></tr><tr><td>Database</td><td>✓</td><td>✓</td><td></td><td></td></tr><tr><td>Source</td><td></td><td></td><td>✓</td><td></td></tr><tr><td>Sink</td><td></td><td></td><td>✓</td><td></td></tr><tr><td><a href="https://realfuture.ai/blog/2025/06/26/#42-%E6%A0%A1%E9%AA%8C">校验</a></td><td>✓</td><td>✓</td><td>✓</td><td></td></tr><tr><td><a href="https://realfuture.ai/blog/2025/06/26/#43-%E8%BF%90%E8%A1%8C">运行</a></td><td>✓</td><td>✓</td><td></td><td></td></tr><tr><td>暂停预览</td><td>✓</td><td>✓</td><td></td><td></td></tr><tr><td>恢复预览</td><td>✓</td><td>✓</td><td></td><td></td></tr><tr><td>停止预览</td><td>✓</td><td>✓</td><td></td><td></td></tr><tr><td><a href="https://realfuture.ai/blog/2025/06/26/#44-%E6%9F%A5%E7%9C%8B%E5%8F%98%E9%87%8F%E4%BD%BF%E7%94%A8">查看变量使用</a></td><td>✓</td><td>✓</td><td>✓</td><td></td></tr><tr><td>清空选项（清空 Flink Env 、Catalog 和 Database 的数据）</td><td>✓</td><td>✓</td><td></td><td></td></tr></tbody></table>
<h4 class="anchor anchorWithStickyNavbar_I2Xo" id="2104-配置栏">2.10.4 配置栏<a href="https://realfuture.ai/blog/2025/06/26/#2104-%E9%85%8D%E7%BD%AE%E6%A0%8F" class="hash-link" aria-label="Direct link to 2.10.4 配置栏" title="Direct link to 2.10.4 配置栏">​</a></h4>
<p>配置栏是对当前作业进行额外配置的部分，它包含询问 <code>AI</code> 、 <code>Flink</code> 配置、 <code>Hadoop</code> 配置、 <code>Kubernetes</code> 配置、告警配置、作业依赖和历史版本。</p>
<div class="theme-admonition theme-admonition-warning admonition_kxJD alert alert--warning"><div class="admonitionHeading_JQHl"><span class="admonitionIcon_Nmmf"><svg viewBox="0 0 16 16"><path fill-rule="evenodd" d="M8.893 1.5c-.183-.31-.52-.5-.887-.5s-.703.19-.886.5L.138 13.499a.98.98 0 0 0 0 1.001c.193.31.53.501.886.501h13.964c.367 0 .704-.19.877-.5a1.03 1.03 0 0 0 .01-1.002L8.893 1.5zm.133 11.497H6.987v-2.003h2.039v2.003zm0-3.004H6.987V5.987h2.039v4.006z"></path></svg></span>注意</div><div class="admonitionContent_i_yp"><p>额外的配置会根据作业类型和 <code>Flink Env</code> 等因素发生进行变化。</p></div></div>
<h2 class="anchor anchorWithStickyNavbar_I2Xo" id="3-开发区域">3. 开发区域<a href="https://realfuture.ai/blog/2025/06/26/#3-%E5%BC%80%E5%8F%91%E5%8C%BA%E5%9F%9F" class="hash-link" aria-label="Direct link to 3. 开发区域" title="Direct link to 3. 开发区域">​</a></h2>
<p>开发区域是作业开发调试工具的核心之一，每种作业类型都会有一个开发区域。</p>
<p><code>SQL</code> 查询和 <code>SQL</code> 作业的开发区域功能一致，所以不再赘述。</p>
<h3 class="anchor anchorWithStickyNavbar_I2Xo" id="31-sql-作业">3.1 SQL 作业<a href="https://realfuture.ai/blog/2025/06/26/#31-sql-%E4%BD%9C%E4%B8%9A" class="hash-link" aria-label="Direct link to 3.1 SQL 作业" title="Direct link to 3.1 SQL 作业">​</a></h3>
<p>新创建的 <code>SQL</code> 作业顶部会有默认的注释信息，其中包含作者、创建时间和语法提示。</p>
<p><code>SQL</code> 作业的编辑器支持右键菜单，菜单中包含格式化、全屏、运行、校验以及 <code>IDE</code> 内置的功能。</p>
<div data-rmiz=""><div data-rmiz-content="not-found" style="visibility:visible"><img src="https://realfuture.ai/img/blog/2025-06-26/sql-ide.png" alt="sql-ide" style="cursor:pointer"></div></div>
<p><code>SQL</code> 作业支持选中运行，默认的运行会运行整个 <code>IDE</code> 内容，选中运行则只会运行选中的内容。</p>
<div class="theme-admonition theme-admonition-tip admonition_kxJD alert alert--success"><div class="admonitionHeading_JQHl"><span class="admonitionIcon_Nmmf"><svg viewBox="0 0 12 16"><path fill-rule="evenodd" d="M6.5 0C3.48 0 1 2.19 1 5c0 .92.55 2.25 1 3 1.34 2.25 1.78 2.78 2 4v1h5v-1c.22-1.22.66-1.75 2-4 .45-.75 1-2.08 1-3 0-2.81-2.48-5-5.5-5zm3.64 7.48c-.25.44-.47.8-.67 1.11-.86 1.41-1.25 2.06-1.45 3.23-.02.05-.02.11-.02.17H5c0-.06 0-.13-.02-.17-.2-1.17-.59-1.83-1.45-3.23-.2-.31-.42-.67-.67-1.11C2.44 6.78 2 5.65 2 5c0-2.2 2.02-4 4.5-4 1.22 0 2.36.42 3.22 1.19C10.55 2.94 11 3.94 11 5c0 .66-.44 1.78-.86 2.48zM4 14h5c-.23 1.14-1.3 2-2.5 2s-2.27-.86-2.5-2z"></path></svg></span>提示</div><div class="admonitionContent_i_yp"><p>运行选中内容可以使用快捷键进行操作，<code>Windows</code> 系统为 <code>Ctrl + e</code>， <code>Mac OS</code> 系统为 <code>Command + e</code>。</p></div></div>
<div data-rmiz=""><div data-rmiz-content="not-found" style="visibility:visible"><img src="https://realfuture.ai/img/blog/2025-06-26/sql-select-run.png" alt="sql-select-run" style="cursor:pointer"></div></div>
<p><code>SQL</code> 作业支持语法、 <code>Catalog</code> 、 <code>Database</code> 、 <code>Table</code> 、 <code>View</code> 和变量的补全功能。</p>
<div data-rmiz=""><div data-rmiz-content="not-found" style="visibility:visible"><img src="https://realfuture.ai/img/blog/2025-06-26/sql-suggest.png" alt="sql-suggest" style="cursor:pointer"></div></div>
<h3 class="anchor anchorWithStickyNavbar_I2Xo" id="32-cdc-作业">3.2 CDC 作业<a href="https://realfuture.ai/blog/2025/06/26/#32-cdc-%E4%BD%9C%E4%B8%9A" class="hash-link" aria-label="Direct link to 3.2 CDC 作业" title="Direct link to 3.2 CDC 作业">​</a></h3>
<p>新创建的 <code>CDC</code> 作业顶部会有默认的注释信息，其中包含作者、创建时间和描述等信息。</p>
<p><code>CDC</code> 作业的编辑器支持右键菜单，菜单中包含全屏、校验以及 <code>IDE</code> 内置的功能。</p>
<div data-rmiz=""><div data-rmiz-content="not-found" style="visibility:visible"><img src="https://realfuture.ai/img/blog/2025-06-26/cdc-ide.png" alt="cdc-ide" style="cursor:pointer"></div></div>
<p><code>CDC</code> 作业支持变量的补全功能，可以通过 <code>$</code> 符进行触发。</p>
<div data-rmiz=""><div data-rmiz-content="not-found" style="visibility:visible"><img src="https://realfuture.ai/img/blog/2025-06-26/cdc-suggest.png" alt="cdc-suggest" style="cursor:pointer"></div></div>
<h3 class="anchor anchorWithStickyNavbar_I2Xo" id="33-jar-作业">3.3 JAR 作业<a href="https://realfuture.ai/blog/2025/06/26/#33-jar-%E4%BD%9C%E4%B8%9A" class="hash-link" aria-label="Direct link to 3.3 JAR 作业" title="Direct link to 3.3 JAR 作业">​</a></h3>
<p><code>JAR</code> 作业的程序 <code>Jar</code> 字段支持从 <code>JAR</code> 资源面板拖拽资源，程序参数字段支持全屏以及 <code>IDE</code> 内置的右键功能。</p>
<div data-rmiz=""><div data-rmiz-content="not-found" style="visibility:visible"><img src="https://realfuture.ai/img/blog/2025-06-26/jar-form.png" alt="jar-form" style="cursor:pointer"></div></div>
<h2 class="anchor anchorWithStickyNavbar_I2Xo" id="4-标签栏">4. 标签栏<a href="https://realfuture.ai/blog/2025/06/26/#4-%E6%A0%87%E7%AD%BE%E6%A0%8F" class="hash-link" aria-label="Direct link to 4. 标签栏" title="Direct link to 4. 标签栏">​</a></h2>
<h3 class="anchor anchorWithStickyNavbar_I2Xo" id="41-作业发布">4.1 作业发布<a href="https://realfuture.ai/blog/2025/06/26/#41-%E4%BD%9C%E4%B8%9A%E5%8F%91%E5%B8%83" class="hash-link" aria-label="Direct link to 4.1 作业发布" title="Direct link to 4.1 作业发布">​</a></h3>
<p>作业发布详情在打开作业时就会开始轮询，用以获取发布的状态和信息。</p>
<p>作业发布按钮如果为禁用状态时，则无法执行发布作业的操作。</p>
<div data-rmiz=""><div data-rmiz-content="not-found" style="visibility:visible"><img src="https://realfuture.ai/img/blog/2025-06-26/release.png" alt="release" style="cursor:pointer"></div></div>
<p>如果出现发布 <code>Pipeline</code> 详情时，可以通过点击发布按钮右侧的状态查看发布 <code>Pipeline</code> 详情，如果作业发布失败还可查看失败的 <code>Pipeline</code> 日志。</p>
<div data-rmiz=""><div data-rmiz-content="not-found" style="visibility:visible"><img src="https://realfuture.ai/img/blog/2025-06-26/release-pipeline.png" alt="release-pipeline" style="cursor:pointer"></div></div>
<div class="theme-admonition theme-admonition-tip admonition_kxJD alert alert--success"><div class="admonitionHeading_JQHl"><span class="admonitionIcon_Nmmf"><svg viewBox="0 0 12 16"><path fill-rule="evenodd" d="M6.5 0C3.48 0 1 2.19 1 5c0 .92.55 2.25 1 3 1.34 2.25 1.78 2.78 2 4v1h5v-1c.22-1.22.66-1.75 2-4 .45-.75 1-2.08 1-3 0-2.81-2.48-5-5.5-5zm3.64 7.48c-.25.44-.47.8-.67 1.11-.86 1.41-1.25 2.06-1.45 3.23-.02.05-.02.11-.02.17H5c0-.06 0-.13-.02-.17-.2-1.17-.59-1.83-1.45-3.23-.2-.31-.42-.67-.67-1.11C2.44 6.78 2 5.65 2 5c0-2.2 2.02-4 4.5-4 1.22 0 2.36.42 3.22 1.19C10.55 2.94 11 3.94 11 5c0 .66-.44 1.78-.86 2.48zM4 14h5c-.23 1.14-1.3 2-2.5 2s-2.27-.86-2.5-2z"></path></svg></span>提示</div><div class="admonitionContent_i_yp"><p>作业发布会优先校验 <code>Flink</code> 环境、 <code>Kubernetes</code> 配置（ <code>Kubernetes</code> 配置存在警告信息时，不会阻止作业发布）然后执行校验（ <code>JAR</code> 作业不会执行），当完成上述步骤时，才会执行发布动作。</p></div></div>
<h3 class="anchor anchorWithStickyNavbar_I2Xo" id="42-校验">4.2 校验<a href="https://realfuture.ai/blog/2025/06/26/#42-%E6%A0%A1%E9%AA%8C" class="hash-link" aria-label="Direct link to 4.2 校验" title="Direct link to 4.2 校验">​</a></h3>
<p>校验功能只有在非 <code>JAR</code> 作业下才会出现。校验结果总共有三种状态，分别是成功、错误和警告。</p>
<p>错误和警告会在对应编辑器中标出红色和黄色且鼠标移入后可以查看对应的信息。</p>
<p>错误和警告在结果面板也可以展开查看更完整的信息。</p>
<div data-rmiz=""><div data-rmiz-content="not-found" style="visibility:visible"><img src="https://realfuture.ai/img/blog/2025-06-26/validate-warning.png" alt="validate-warning" style="cursor:pointer"></div></div>
<div data-rmiz=""><div data-rmiz-content="not-found" style="visibility:visible"><img src="https://realfuture.ai/img/blog/2025-06-26/validate-error.png" alt="validate-error" style="cursor:pointer"></div></div>
<h3 class="anchor anchorWithStickyNavbar_I2Xo" id="43-运行">4.3 运行<a href="https://realfuture.ai/blog/2025/06/26/#43-%E8%BF%90%E8%A1%8C" class="hash-link" aria-label="Direct link to 4.3 运行" title="Direct link to 4.3 运行">​</a></h3>
<p>当用户点击运行功能时，会优先处理校验逻辑，当校验的结果没有问题时，才会执行运行操作。</p>
<p>运行功能只会在 <code>SQL</code> 查询和 <code>SQL</code> 作业时才会出现。</p>
<p>如果当前作业没有选择过预览集群，则会出现选择预览集群的选项。</p>
<div data-rmiz=""><div data-rmiz-content="not-found" style="visibility:visible"><img src="https://realfuture.ai/img/blog/2025-06-26/preview-cluster.png" alt="preview-cluster" style="cursor:pointer"></div></div>
<p>选择集群点击确定后，就可以在结果面板实时预览数据。</p>
<p>作业在预览的过程中时运行图标会更换为暂停和停止，当点击暂停图标时，会暂停当前预览，用户可通过点击恢复按钮，恢复当前预览。</p>
<div data-rmiz=""><div data-rmiz-content="not-found" style="visibility:visible"><img src="https://realfuture.ai/img/blog/2025-06-26/preview.png" alt="preview" style="cursor:pointer"></div></div>
<h3 class="anchor anchorWithStickyNavbar_I2Xo" id="44-查看变量使用">4.4 查看变量使用<a href="https://realfuture.ai/blog/2025/06/26/#44-%E6%9F%A5%E7%9C%8B%E5%8F%98%E9%87%8F%E4%BD%BF%E7%94%A8" class="hash-link" aria-label="Direct link to 4.4 查看变量使用" title="Direct link to 4.4 查看变量使用">​</a></h3>
<p>查看变量使用只有在非 <code>JAR</code> 作业下才可使用。如果作业编辑器中存在变量相关的内容，在用户点击查看变量时候后，会出现一个代码对比弹窗，其中左侧为当前代码，右侧为当前代码变量解析后的代码。</p>
<div data-rmiz=""><div data-rmiz-content="not-found" style="visibility:visible"><img src="https://realfuture.ai/img/blog/2025-06-26/show-var-use.png" alt="show-var-use" style="cursor:pointer"></div></div>
<h2 class="anchor anchorWithStickyNavbar_I2Xo" id="5-配置栏">5. 配置栏<a href="https://realfuture.ai/blog/2025/06/26/#5-%E9%85%8D%E7%BD%AE%E6%A0%8F" class="hash-link" aria-label="Direct link to 5. 配置栏" title="Direct link to 5. 配置栏">​</a></h2>
<h3 class="anchor anchorWithStickyNavbar_I2Xo" id="51-询问-ai">5.1 询问 AI<a href="https://realfuture.ai/blog/2025/06/26/#51-%E8%AF%A2%E9%97%AE-ai" class="hash-link" aria-label="Direct link to 5.1 询问 AI" title="Direct link to 5.1 询问 AI">​</a></h3>
<p>询问 <code>AI</code> 的功能只在 <code>SQL</code> 查询和 <code>SQL</code> 作业才会出现。</p>
<div data-rmiz=""><div data-rmiz-content="not-found" style="visibility:visible"><img src="https://realfuture.ai/img/blog/2025-06-26/ai.png" alt="ai" style="cursor:pointer"></div></div>
<p><code>AI</code> 助手支持四种模型的切换，分别是 <code>deepseek-reasoner</code> 、 <code>deepseek-r1-250120</code> 、 <code>deepseek-coder-v2:latest</code> 和 <code>qwen2.5-coder:7b</code>。</p>
<div data-rmiz=""><div data-rmiz-content="not-found" style="visibility:visible"><img src="https://realfuture.ai/img/blog/2025-06-26/ai-mode.png" alt="ai-mode" style="cursor:pointer"></div></div>
<p><code>AI</code> 助手返回的代码提供插入和复制的功能，插入功能可以直接把返回的代码插入到 <code>SQL</code> 编辑器中，复制功能可以把返回的代码复制到系统剪贴板。</p>
<div data-rmiz=""><div data-rmiz-content="not-found" style="visibility:visible"><img src="https://realfuture.ai/img/blog/2025-06-26/ai-action.png" alt="ai-action" style="cursor:pointer"></div></div>
<h3 class="anchor anchorWithStickyNavbar_I2Xo" id="52-flink-配置">5.2 Flink 配置<a href="https://realfuture.ai/blog/2025/06/26/#52-flink-%E9%85%8D%E7%BD%AE" class="hash-link" aria-label="Direct link to 5.2 Flink 配置" title="Direct link to 5.2 Flink 配置">​</a></h3>
<p><code>Flink</code> 配置将常见字段转换成对应的表单项，对于其它不常见配置也提供了相应的代码补全的能力。</p>
<div data-rmiz=""><div data-rmiz-content="not-found" style="visibility:visible"><img src="https://realfuture.ai/img/blog/2025-06-26/flink-setting.png" alt="flink-setting" style="cursor:pointer"></div></div>
<h3 class="anchor anchorWithStickyNavbar_I2Xo" id="53-hadoop-配置">5.3 Hadoop 配置<a href="https://realfuture.ai/blog/2025/06/26/#53-hadoop-%E9%85%8D%E7%BD%AE" class="hash-link" aria-label="Direct link to 5.3 Hadoop 配置" title="Direct link to 5.3 Hadoop 配置">​</a></h3>
<p><code>Hadoop</code> 配置只有在 <code>Flink</code> 环境部署模式为 <code>Yarn Application</code> 或 <code>Yarn Per Job</code> 时才会出现。</p>
<div data-rmiz=""><div data-rmiz-content="not-found" style="visibility:visible"><img src="https://realfuture.ai/img/blog/2025-06-26/hadoop.png" alt="hadoop" style="cursor:pointer"></div></div>
<h3 class="anchor anchorWithStickyNavbar_I2Xo" id="54-kubernetes-配置">5.4 Kubernetes 配置<a href="https://realfuture.ai/blog/2025/06/26/#54-kubernetes-%E9%85%8D%E7%BD%AE" class="hash-link" aria-label="Direct link to 5.4 Kubernetes 配置" title="Direct link to 5.4 Kubernetes 配置">​</a></h3>
<p><code>Kubernetes</code> 配置是一个支持表单校验的特殊配置，在进入作业时就会自动校验。它的按钮也分为五种状态，分别是禁用、警告、错误、激活（打开 <code>Kubernetes</code> 配置）和未激活（未打开 <code>Kubernetes</code> 配置）。</p>
<p><code>Kubernetes</code> 配置的扩容条件有四种，分别是 <code>CPU</code> 、 <code>CPU</code> 和内存、内存和自定义规则。</p>
<p><code>Kubernetes</code> 配置只有在 <code>Flink</code> 环境部署模式为 <code>K8s Application</code> 时才会出现。</p>
<div data-rmiz=""><div data-rmiz-content="not-found" style="visibility:visible"><img src="https://realfuture.ai/img/blog/2025-06-26/kubernetes.png" alt="kubernetes" style="cursor:pointer"></div></div>
<p>如果 <code>Flink</code> 环境中的 <code>Flink</code> 版本为空时，则会禁用 <code>Kubernetes</code> 配置。</p>
<div data-rmiz=""><div data-rmiz-content="not-found" style="visibility:visible"><img src="https://realfuture.ai/img/blog/2025-06-26/kubernetes-disabled.png" alt="kubernetes-disabled" style="cursor:pointer"></div></div>
<p>当 <code>Kubernetes</code> 配置的表单项存在错误时，对应的表单项和按钮都会标红。</p>
<div data-rmiz=""><div data-rmiz-content="not-found" style="visibility:visible"><img src="https://realfuture.ai/img/blog/2025-06-26/kubernetes-error.png" alt="kubernetes-error" style="cursor:pointer"></div></div>
<p>当 <code>Kubernetes</code> 配置的 <code>Flink</code> 镜像存在警告信息时，表单项和按钮会对应标黄。</p>
<div data-rmiz=""><div data-rmiz-content="not-found" style="visibility:visible"><img src="https://realfuture.ai/img/blog/2025-06-26/kubernetes-warning.png" alt="kubernetes-warning" style="cursor:pointer"></div></div>
<h3 class="anchor anchorWithStickyNavbar_I2Xo" id="55-告警配置">5.5 告警配置<a href="https://realfuture.ai/blog/2025/06/26/#55-%E5%91%8A%E8%AD%A6%E9%85%8D%E7%BD%AE" class="hash-link" aria-label="Direct link to 5.5 告警配置" title="Direct link to 5.5 告警配置">​</a></h3>
<p>告警配置只在非 <code>SQL</code> 查询时才会出现，它跟作业的其它配置没有任何的联动关系。</p>
<div data-rmiz=""><div data-rmiz-content="not-found" style="visibility:visible"><img src="https://realfuture.ai/img/blog/2025-06-26/alert.png" alt="alert" style="cursor:pointer"></div></div>
<h3 class="anchor anchorWithStickyNavbar_I2Xo" id="56-作业依赖">5.6 作业依赖<a href="https://realfuture.ai/blog/2025/06/26/#56-%E4%BD%9C%E4%B8%9A%E4%BE%9D%E8%B5%96" class="hash-link" aria-label="Direct link to 5.6 作业依赖" title="Direct link to 5.6 作业依赖">​</a></h3>
<p>作业依赖在四种作业类型中都会出现，并且跟作业的其它配置没有任何的联动关系。</p>
<p>作业依赖会自动识别除 <code>JAR</code> 作业以外的作业依赖，用户也可手动更改作业依赖。</p>
<div data-rmiz=""><div data-rmiz-content="not-found" style="visibility:visible"><img src="https://realfuture.ai/img/blog/2025-06-26/dep.png" alt="dep" style="cursor:pointer"></div></div>
<h3 class="anchor anchorWithStickyNavbar_I2Xo" id="57-历史版本">5.7 历史版本<a href="https://realfuture.ai/blog/2025/06/26/#57-%E5%8E%86%E5%8F%B2%E7%89%88%E6%9C%AC" class="hash-link" aria-label="Direct link to 5.7 历史版本" title="Direct link to 5.7 历史版本">​</a></h3>
<p><code>JAR</code> 作业的历史版本不支持操作功能，<code>SQL</code> 查询没有历史版本功能。</p>
<p>历史版本的操作有查看、对比、回滚和删除。</p>
<div data-rmiz=""><div data-rmiz-content="not-found" style="visibility:visible"><img src="https://realfuture.ai/img/blog/2025-06-26/history.png" alt="history" style="cursor:pointer"></div></div>
<p>历史版本可以选择某一个版本进行对比，通过对比可以看到两个版本之间的差异，弹窗左侧为当前版本，右侧为对应的历史版本。</p>
<div data-rmiz=""><div data-rmiz-content="not-found" style="visibility:visible"><img src="https://realfuture.ai/img/blog/2025-06-26/history-diff.png" alt="history-diff" style="cursor:pointer"></div></div>
<h2 class="anchor anchorWithStickyNavbar_I2Xo" id="6-快捷导览">6. 快捷导览<a href="https://realfuture.ai/blog/2025/06/26/#6-%E5%BF%AB%E6%8D%B7%E5%AF%BC%E8%A7%88" class="hash-link" aria-label="Direct link to 6. 快捷导览" title="Direct link to 6. 快捷导览">​</a></h2>
<p>由于此篇文章内容过多，为此提供了快速导览的功能，以帮助您快速了解。</p>
<h3 class="anchor anchorWithStickyNavbar_I2Xo" id="61-如何创建作业">6.1 如何创建作业<a href="https://realfuture.ai/blog/2025/06/26/#61-%E5%A6%82%E4%BD%95%E5%88%9B%E5%BB%BA%E4%BD%9C%E4%B8%9A" class="hash-link" aria-label="Direct link to 6.1 如何创建作业" title="Direct link to 6.1 如何创建作业">​</a></h3>
<p>在作业开发调试工具中，用户有三种创建作业的方式，您可通过点击链接的形式跳转到该文章的对应位置获取更详细的介绍：</p>
<ul>
<li>通过 <a href="https://realfuture.ai/blog/2025/06/26/#1-%E8%90%BD%E5%9C%B0%E9%A1%B5">落地页</a> 创建作业。</li>
<li>通过作业草稿面板的 <a href="https://realfuture.ai/blog/2025/06/26/#22-%E8%B5%84%E6%BA%90%E9%9D%A2%E6%9D%BF%E7%9A%84%E6%93%8D%E4%BD%9C%E6%A0%8F">操作栏</a> 创建作业。</li>
<li>通过 <a href="https://realfuture.ai/blog/2025/06/26/#23-%E4%BD%9C%E4%B8%9A%E8%8D%89%E7%A8%BF%E9%9D%A2%E6%9D%BF">作业草稿面板</a> 的文件夹操作列表创建作业（默认存储位置是当前选择的文件夹）。</li>
</ul>
<h3 class="anchor anchorWithStickyNavbar_I2Xo" id="62-作业都有哪些类型">6.2 作业都有哪些类型<a href="https://realfuture.ai/blog/2025/06/26/#62-%E4%BD%9C%E4%B8%9A%E9%83%BD%E6%9C%89%E5%93%AA%E4%BA%9B%E7%B1%BB%E5%9E%8B" class="hash-link" aria-label="Direct link to 6.2 作业都有哪些类型" title="Direct link to 6.2 作业都有哪些类型">​</a></h3>
<p>目前作业开发调试工具支持四种作业类型，分别是 <code>JAR</code> 、 <code>CDC</code> 、 <code>SQL</code> 和 <code>SQL</code> 查询。其中 <code>SQL</code> 查询是一种内置的无法被删除的特殊作业类型，它具备了除发布以外的所有 <code>SQL</code> 作业应有的能力，它能帮助用户更快捷的执行一些操作。</p>
<h3 class="anchor anchorWithStickyNavbar_I2Xo" id="63-资源面板都有哪些">6.3 资源面板都有哪些<a href="https://realfuture.ai/blog/2025/06/26/#63-%E8%B5%84%E6%BA%90%E9%9D%A2%E6%9D%BF%E9%83%BD%E6%9C%89%E5%93%AA%E4%BA%9B" class="hash-link" aria-label="Direct link to 6.3 资源面板都有哪些" title="Direct link to 6.3 资源面板都有哪些">​</a></h3>
<p>资源面板包括 <a href="https://realfuture.ai/blog/2025/06/26/#23-%E4%BD%9C%E4%B8%9A%E8%8D%89%E7%A8%BF%E9%9D%A2%E6%9D%BF">作业草稿面板</a> 、<a href="https://realfuture.ai/blog/2025/06/26/#24-%E5%85%83%E6%95%B0%E6%8D%AE%E9%9D%A2%E6%9D%BF">元数据面板</a>、<a href="https://realfuture.ai/blog/2025/06/26/#25-udf-%E7%AE%A1%E7%90%86%E9%9D%A2%E6%9D%BF">UDF 管理面板</a> 和 <a href="https://realfuture.ai/blog/2025/06/26/#26-jar-%E8%B5%84%E6%BA%90%E9%9D%A2%E6%9D%BF">JAR 资源面板</a>。</p>]]></content:encoded>
            <category>Realfuture</category>
        </item>
        <item>
            <title><![CDATA[Flink CDC 一键同步]]></title>
            <link>https://realfuture.ai/blog/2025/06/25/</link>
            <guid>https://realfuture.ai/blog/2025/06/25/</guid>
            <pubDate>Wed, 25 Jun 2025 00:00:00 GMT</pubDate>
            <description><![CDATA[本文使用 Awestream 预置的 demo_cdc 模板，演示从 MySQL 到 Doris 的实时数据同步流程。]]></description>
            <content:encoded><![CDATA[<p>在实时数据场景中，数据同步并不新鲜，真正的挑战是同时做到高效、低门槛和可观测。本文将从零开始，使用 Awestream 完成一套从 MySQL 到 Doris 的 Flink CDC 实时数据同步，整个配置流程约需 5 分钟。</p>
<p>🔥 核心亮点</p>
<ul>
<li>1️⃣ 极简开发：用 Awestream 平台像 “写表格、改配置” 一样轻松开发CDC作业，告别复杂代码！</li>
<li>2️⃣ 5 分钟完成配置：从 MySQL + Doris 环境到同步配置和上线运维，新用户也能快速上手。</li>
<li>3️⃣ 企业级能力：可视化运维、智能扩缩容、秒级响应，满足实时数据湖仓一体化需求。</li>
</ul>
<!-- -->
<h2 class="anchor anchorWithStickyNavbar_I2Xo" id="一什么是-flink-cdc">一、什么是 Flink CDC<a href="https://realfuture.ai/blog/2025/06/25/#%E4%B8%80%E4%BB%80%E4%B9%88%E6%98%AF-flink-cdc" class="hash-link" aria-label="Direct link to 一、什么是 Flink CDC" title="Direct link to 一、什么是 Flink CDC">​</a></h2>
<p>Flink CDC 是一个数据集成框架，它基于数据库日志的 CDC（变更数据捕获）技术实现了统一的增量和全量数据读取。结合 Flink 出色的管道能力和丰富的上下游生态系统，Flink CDC 可以高效地实现海量数据的实时集成。
Flink CDC 可以应用在多种场景中。比如数据同步，可以将上游数据库中的数据同步至下游数据仓库、数据湖等。用户还可以借助 Flink CDC source 实现实时物化视图，结合下游 Flink 作业处理逻辑实现更丰富的业务场景。此外用户还可以使用 Flink CDC 捕获的变更数据基于业务逻辑进行数据分发。
作为一款数据集成框架，Flink CDC 对接了非常丰富的上下游数据库、数据湖仓和消息队列等外部系统，如 MySQL、PostgreSQL、Kafka、Paimon 等。</p>
<div data-rmiz=""><div data-rmiz-content="not-found" style="visibility:visible"><img src="https://realfuture.ai/img/blog/2025-06-25/cdc.png" alt="Flink CDC" style="cursor:pointer"></div></div>
<h2 class="anchor anchorWithStickyNavbar_I2Xo" id="二awestream-是什么">二、Awestream 是什么<a href="https://realfuture.ai/blog/2025/06/25/#%E4%BA%8Cawestream-%E6%98%AF%E4%BB%80%E4%B9%88" class="hash-link" aria-label="Direct link to 二、Awestream 是什么" title="Direct link to 二、Awestream 是什么">​</a></h2>
<p>Awestream 是由实时未来科技(由 Apache StreamPark 创始团队成立) 推出的，基于 Apache StreamPark 和 Apache Flink 构建的新一代实时计算产品，专为企业打造，集实时计算、数据湖、数据仓库于一体，彻底解决传统流式计算复杂、门槛高、运维难的问题。
在 Awestream 中开发实时作业就像写 SQL 一样简单，全程极致流程的开发体验，作业运维可视化、自动化、秒级响应，资源调度自动扩缩容，降本增效... 不论是业务监控、实时运营分析、数据同步，还是数据湖仓一体化建设，Awestream 都能提供开箱即用、企业级标准的流计算方案，让复杂的大数据开发、实时数据同步，变得像写表格、配公式一样简单高效，
助力企业轻松应对 AI 时代的实时数据挑战。</p>
<p>Awestream 组件架构图 </p><div data-rmiz=""><div data-rmiz-content="not-found" style="visibility:visible"><img src="https://realfuture.ai/img/awestream.png" alt="Awestream" style="cursor:pointer"></div></div><p></p>
<h2 class="anchor anchorWithStickyNavbar_I2Xo" id="三基于-awestream-的-flink-cdc-一键同步数据方案">三、基于 Awestream 的 Flink CDC 一键同步数据方案<a href="https://realfuture.ai/blog/2025/06/25/#%E4%B8%89%E5%9F%BA%E4%BA%8E-awestream-%E7%9A%84-flink-cdc-%E4%B8%80%E9%94%AE%E5%90%8C%E6%AD%A5%E6%95%B0%E6%8D%AE%E6%96%B9%E6%A1%88" class="hash-link" aria-label="Direct link to 三、基于 Awestream 的 Flink CDC 一键同步数据方案" title="Direct link to 三、基于 Awestream 的 Flink CDC 一键同步数据方案">​</a></h2>
<p>接下来通过 Awestream 平台来演示一整套实时数据同步流程，包含：</p>
<ul>
<li>数据库环境部署（ MySQL + Doris ）</li>
<li>CDC 作业开发</li>
<li>作业发布与运维</li>
</ul>
<h2 class="anchor anchorWithStickyNavbar_I2Xo" id="环境准备">环境准备<a href="https://realfuture.ai/blog/2025/06/25/#%E7%8E%AF%E5%A2%83%E5%87%86%E5%A4%87" class="hash-link" aria-label="Direct link to 环境准备" title="Direct link to 环境准备">​</a></h2>
<p>首先需要准备一台安装了 <code>Docker</code> 和 <code>Docker Compose</code> 的 <code>Linux</code> 或 <code>macOS</code> 计算机。</p>
<h3 class="anchor anchorWithStickyNavbar_I2Xo" id="mysql-安装">MySQL 安装<a href="https://realfuture.ai/blog/2025/06/25/#mysql-%E5%AE%89%E8%A3%85" class="hash-link" aria-label="Direct link to MySQL 安装" title="Direct link to MySQL 安装">​</a></h3>
<p>在终端执行如下命令，使用 <code>docker</code> 安装 <code>MySQL</code>：</p>
<div class="language-shell codeBlockContainer_eR_5 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_jz8P"><pre tabindex="0" class="prism-code language-shell codeBlock_tQzK thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_J4lo"><span class="token-line" style="color:#F8F8F2"><span class="token plain"># 拉取 MySQL 镜像</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">docker pull --platform linux/amd64 mysql:8.0.25</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"># 创建并运行 MySQL 容器</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">docker run -d -p 30025:3306 --name mysql8.0.25 -e MYSQL_ROOT_PASSWORD=root mysql:8.0.25</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"># 使用如下命令校验 MySQL 是否安装成功</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">docker ps -a |grep mysql</span><br></span></code></pre><div class="buttonGroup_EiCC"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_azoe" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_HjTd"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_dSkr"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<div class="theme-admonition theme-admonition-tip admonition_kxJD alert alert--success"><div class="admonitionHeading_JQHl"><span class="admonitionIcon_Nmmf"><svg viewBox="0 0 12 16"><path fill-rule="evenodd" d="M6.5 0C3.48 0 1 2.19 1 5c0 .92.55 2.25 1 3 1.34 2.25 1.78 2.78 2 4v1h5v-1c.22-1.22.66-1.75 2-4 .45-.75 1-2.08 1-3 0-2.81-2.48-5-5.5-5zm3.64 7.48c-.25.44-.47.8-.67 1.11-.86 1.41-1.25 2.06-1.45 3.23-.02.05-.02.11-.02.17H5c0-.06 0-.13-.02-.17-.2-1.17-.59-1.83-1.45-3.23-.2-.31-.42-.67-.67-1.11C2.44 6.78 2 5.65 2 5c0-2.2 2.02-4 4.5-4 1.22 0 2.36.42 3.22 1.19C10.55 2.94 11 3.94 11 5c0 .66-.44 1.78-.86 2.48zM4 14h5c-.23 1.14-1.3 2-2.5 2s-2.27-.86-2.5-2z"></path></svg></span>温馨提示</div><div class="admonitionContent_i_yp"><p>安装完成后，MySQL 的登录账号和密码为：root/root</p></div></div>
<h3 class="anchor anchorWithStickyNavbar_I2Xo" id="doris-安装">Doris 安装<a href="https://realfuture.ai/blog/2025/06/25/#doris-%E5%AE%89%E8%A3%85" class="hash-link" aria-label="Direct link to Doris 安装" title="Direct link to Doris 安装">​</a></h3>
<p>首先需要设置 <code>max_map_count</code>，该参数用于控制进程可以映射的最大内存区域数量。</p>
<blockquote>
<p>Doris 在运行时会使用大量的内存映射（mmap）操作来管理数据，如果 max_map_count 的值太低，可能会导致 Doris 无法正常启动或运行。</p>
</blockquote>
<p>在主机上执行以下命令：</p>
<div class="language-shell codeBlockContainer_eR_5 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_jz8P"><pre tabindex="0" class="prism-code language-shell codeBlock_tQzK thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_J4lo"><span class="token-line" style="color:#F8F8F2"><span class="token plain">sysctl -w vm.max_map_count=2000000</span><br></span></code></pre><div class="buttonGroup_EiCC"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_azoe" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_HjTd"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_dSkr"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>在 <code>macOS</code> 上，由于 <code>Docker</code> 容器的运行方式与 <code>Linux</code> 不同，直接在宿主机上修改 <code>max_map_count</code> 可能不会生效。这是因为 <code>Docker</code> 容器在 <code>macOS</code> 上运行时，实际上通过一个虚拟的 <code>Linux</code> 内核管理容器，而不是直接使用 <code>macOS</code> 内核，因此需要创建特权容器，命令如下：</p>
<div class="language-shell codeBlockContainer_eR_5 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_jz8P"><pre tabindex="0" class="prism-code language-shell codeBlock_tQzK thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_J4lo"><span class="token-line" style="color:#F8F8F2"><span class="token plain"># 1. 创建特权容器</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">docker run -it --privileged --pid=host --name=privileged_container debian nsenter -t 1 -m -u -n -i sh</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"># 2. 设置max_map_count参数</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">sysctl -w vm.max_map_count=2000000</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"># 3. 退出</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">exit</span><br></span></code></pre><div class="buttonGroup_EiCC"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_azoe" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_HjTd"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_dSkr"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>新建 <strong>docker-compose.yaml</strong> 编排文件，写入如下内容：</p>
<div class="theme-admonition theme-admonition-tip admonition_kxJD alert alert--success"><div class="admonitionHeading_JQHl"><span class="admonitionIcon_Nmmf"><svg viewBox="0 0 12 16"><path fill-rule="evenodd" d="M6.5 0C3.48 0 1 2.19 1 5c0 .92.55 2.25 1 3 1.34 2.25 1.78 2.78 2 4v1h5v-1c.22-1.22.66-1.75 2-4 .45-.75 1-2.08 1-3 0-2.81-2.48-5-5.5-5zm3.64 7.48c-.25.44-.47.8-.67 1.11-.86 1.41-1.25 2.06-1.45 3.23-.02.05-.02.11-.02.17H5c0-.06 0-.13-.02-.17-.2-1.17-.59-1.83-1.45-3.23-.2-.31-.42-.67-.67-1.11C2.44 6.78 2 5.65 2 5c0-2.2 2.02-4 4.5-4 1.22 0 2.36.42 3.22 1.19C10.55 2.94 11 3.94 11 5c0 .66-.44 1.78-.86 2.48zM4 14h5c-.23 1.14-1.3 2-2.5 2s-2.27-.86-2.5-2z"></path></svg></span>温馨提示</div><div class="admonitionContent_i_yp"><p>镜像地址需要根据系统来选择（本文使用的是 <code>Mac M</code> 系列的系统，所以这里使用的是 <code>arm</code> 架构）</p></div></div>
<div class="language-yaml codeBlockContainer_eR_5 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_jz8P"><pre tabindex="0" class="prism-code language-yaml codeBlock_tQzK thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_J4lo"><span class="token-line" style="color:#F8F8F2"><span class="token key atrule">services</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token key atrule">docker-fe</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token key atrule">image</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"apache/doris:1.2.2-fe-arm"</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token key atrule">container_name</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"doris-fe"</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token key atrule">hostname</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"fe"</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token key atrule">environment</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">      </span><span class="token punctuation" style="color:rgb(248, 248, 242)">-</span><span class="token plain"> FE_SERVERS=fe1</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain">172.28.0.2</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token number">9001</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">      </span><span class="token punctuation" style="color:rgb(248, 248, 242)">-</span><span class="token plain"> FE_ID=1</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token key atrule">ports</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">      </span><span class="token punctuation" style="color:rgb(248, 248, 242)">-</span><span class="token plain"> 8030</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token number">8030</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">      </span><span class="token punctuation" style="color:rgb(248, 248, 242)">-</span><span class="token plain"> 9030</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token number">9030</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token key atrule">volumes</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">      </span><span class="token punctuation" style="color:rgb(248, 248, 242)">-</span><span class="token plain"> ./data/fe/doris</span><span class="token punctuation" style="color:rgb(248, 248, 242)">-</span><span class="token plain">meta</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain">/opt/apache</span><span class="token punctuation" style="color:rgb(248, 248, 242)">-</span><span class="token plain">doris/fe/doris</span><span class="token punctuation" style="color:rgb(248, 248, 242)">-</span><span class="token plain">meta</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">      </span><span class="token punctuation" style="color:rgb(248, 248, 242)">-</span><span class="token plain"> ./data/fe/conf</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain">/opt/apache</span><span class="token punctuation" style="color:rgb(248, 248, 242)">-</span><span class="token plain">doris/fe/conf</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">      </span><span class="token punctuation" style="color:rgb(248, 248, 242)">-</span><span class="token plain"> ./data/fe/log</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain">/opt/apache</span><span class="token punctuation" style="color:rgb(248, 248, 242)">-</span><span class="token plain">doris/fe/log</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token key atrule">networks</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">      </span><span class="token key atrule">doris_net</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token key atrule">ipv4_address</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> 172.28.0.2</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token key atrule">docker-be</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token key atrule">image</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"apache/doris:1.2.2-be-arm"</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token key atrule">container_name</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"doris-be"</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token key atrule">hostname</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"be"</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token key atrule">depends_on</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">      </span><span class="token punctuation" style="color:rgb(248, 248, 242)">-</span><span class="token plain"> docker</span><span class="token punctuation" style="color:rgb(248, 248, 242)">-</span><span class="token plain">fe</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token key atrule">environment</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">      </span><span class="token punctuation" style="color:rgb(248, 248, 242)">-</span><span class="token plain"> FE_SERVERS=fe1</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain">172.28.0.2</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token number">9001</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">      </span><span class="token punctuation" style="color:rgb(248, 248, 242)">-</span><span class="token plain"> BE_ADDR=172.28.0.3</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token number">9050</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">      </span><span class="token punctuation" style="color:rgb(248, 248, 242)">-</span><span class="token plain"> vm.max_map_count=2000000</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token key atrule">ports</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">      </span><span class="token punctuation" style="color:rgb(248, 248, 242)">-</span><span class="token plain"> 8040</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token number">8040</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token key atrule">volumes</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">      </span><span class="token punctuation" style="color:rgb(248, 248, 242)">-</span><span class="token plain"> ./data/be/storage</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain">/opt/apache</span><span class="token punctuation" style="color:rgb(248, 248, 242)">-</span><span class="token plain">doris/be/storage</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">      </span><span class="token punctuation" style="color:rgb(248, 248, 242)">-</span><span class="token plain"> ./data/be/conf</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain">/opt/apache</span><span class="token punctuation" style="color:rgb(248, 248, 242)">-</span><span class="token plain">doris/be/conf</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">      </span><span class="token punctuation" style="color:rgb(248, 248, 242)">-</span><span class="token plain"> ./data/be/script</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain">/docker</span><span class="token punctuation" style="color:rgb(248, 248, 242)">-</span><span class="token plain">entrypoint</span><span class="token punctuation" style="color:rgb(248, 248, 242)">-</span><span class="token plain">initdb.d</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">      </span><span class="token punctuation" style="color:rgb(248, 248, 242)">-</span><span class="token plain"> ./data/be/log</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain">/opt/apache</span><span class="token punctuation" style="color:rgb(248, 248, 242)">-</span><span class="token plain">doris/be/log</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token key atrule">networks</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">      </span><span class="token key atrule">doris_net</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token key atrule">ipv4_address</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> 172.28.0.3</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token key atrule">networks</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token key atrule">doris_net</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token key atrule">ipam</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">      </span><span class="token key atrule">config</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token punctuation" style="color:rgb(248, 248, 242)">-</span><span class="token plain"> </span><span class="token key atrule">subnet</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> 172.28.0.0/16</span><br></span></code></pre><div class="buttonGroup_EiCC"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_azoe" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_HjTd"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_dSkr"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>执行启动命令：</p>
<div class="language-shell codeBlockContainer_eR_5 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_jz8P"><pre tabindex="0" class="prism-code language-shell codeBlock_tQzK thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_J4lo"><span class="token-line" style="color:#F8F8F2"><span class="token plain"># 启动命令</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">docker-compose -f docker-compose.yaml up -d</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"># 检查是否启动成功</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">docker-compose ps --all</span><br></span></code></pre><div class="buttonGroup_EiCC"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_azoe" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_HjTd"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_dSkr"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>如果出现类似如下提示，表示启动成功：</p>
<div class="language-shell codeBlockContainer_eR_5 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_jz8P"><pre tabindex="0" class="prism-code language-shell codeBlock_tQzK thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_J4lo"><span class="token-line" style="color:#F8F8F2"><span class="token plain">NAME       IMAGE                       COMMAND                  SERVICE     CREATED       STATUS          PORTS</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">doris-be   apache/doris:1.2.2-be-arm   "bash entry_point.sh"    docker-be   3 weeks ago   Up 30 seconds   0.0.0.0:8040-&gt;8040/tcp</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">doris-fe   apache/doris:1.2.2-fe-arm   "/opt/apache-doris/f…"   docker-fe   3 weeks ago   Up 31 seconds   0.0.0.0:8030-&gt;8030/tcp, 0.0.0.0:9030-&gt;9030/tcp</span><br></span></code></pre><div class="buttonGroup_EiCC"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_azoe" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_HjTd"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_dSkr"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>浏览器访问：<a href="http://127.0.0.1:8030/" target="_blank" rel="noopener noreferrer">http://127.0.0.1:8030</a>，登录账号为：<code>admin</code>，无需密码。</p>
<div data-rmiz=""><div data-rmiz-content="not-found" style="visibility:visible"><img src="https://realfuture.ai/img/blog/2025-06-25/doris-login.png" alt="doris-login" style="cursor:pointer"></div></div>
<h2 class="anchor anchorWithStickyNavbar_I2Xo" id="数据准备">数据准备<a href="https://realfuture.ai/blog/2025/06/25/#%E6%95%B0%E6%8D%AE%E5%87%86%E5%A4%87" class="hash-link" aria-label="Direct link to 数据准备" title="Direct link to 数据准备">​</a></h2>
<p>使用客户端（例如 <code>Navicat</code> ）连接 <code>MySQL</code> 数据库，执行如下 <code>SQL</code> 插入数据：</p>
<div class="language-sql codeBlockContainer_eR_5 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_jz8P"><pre tabindex="0" class="prism-code language-sql codeBlock_tQzK thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_J4lo"><span class="token-line" style="color:#F8F8F2"><span class="token comment" style="color:rgb(98, 114, 164)">-- 创建测试数据库</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">CREATE</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">DATABASE</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">IF</span><span class="token plain"> </span><span class="token operator">NOT</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">EXISTS</span><span class="token plain"> db_test</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token comment" style="color:rgb(98, 114, 164)">-- 使用该数据库</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">USE</span><span class="token plain"> db_test</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token comment" style="color:rgb(98, 114, 164)">-- 创建 t_students 表</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">CREATE</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">TABLE</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">IF</span><span class="token plain"> </span><span class="token operator">NOT</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">EXISTS</span><span class="token plain"> t_students </span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    id </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">INT</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">AUTO_INCREMENT</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">PRIMARY</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">KEY</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    name </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">VARCHAR</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token number">20</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token comment" style="color:rgb(98, 114, 164)">-- 插入学生数据</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">INSERT</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">INTO</span><span class="token plain"> t_students </span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">name</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">VALUES</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token string" style="color:rgb(255, 121, 198)">'小明'</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token string" style="color:rgb(255, 121, 198)">'小红'</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token string" style="color:rgb(255, 121, 198)">'小刚'</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token comment" style="color:rgb(98, 114, 164)">-- 创建 t_classes 表</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">CREATE</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">TABLE</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">IF</span><span class="token plain"> </span><span class="token operator">NOT</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">EXISTS</span><span class="token plain"> t_classes </span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    id </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">INT</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">AUTO_INCREMENT</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">PRIMARY</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">KEY</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    class_name </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">VARCHAR</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token number">20</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token comment" style="color:rgb(98, 114, 164)">-- 插入班级数据</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">INSERT</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">INTO</span><span class="token plain"> t_classes </span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">class_name</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">VALUES</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token string" style="color:rgb(255, 121, 198)">'一班'</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token string" style="color:rgb(255, 121, 198)">'二班'</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token string" style="color:rgb(255, 121, 198)">'三班'</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><br></span></code></pre><div class="buttonGroup_EiCC"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_azoe" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_HjTd"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_dSkr"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>执行成功后，可以看到客户端已经创建如下数据：</p>
<div data-rmiz=""><div data-rmiz-content="not-found" style="visibility:visible"><img src="https://realfuture.ai/img/blog/2025-06-25/mysql-test-db.png" alt="mysql-test-db" style="cursor:pointer"></div></div>
<h2 class="anchor anchorWithStickyNavbar_I2Xo" id="cdc-作业开发">CDC 作业开发<a href="https://realfuture.ai/blog/2025/06/25/#cdc-%E4%BD%9C%E4%B8%9A%E5%BC%80%E5%8F%91" class="hash-link" aria-label="Direct link to CDC 作业开发" title="Direct link to CDC 作业开发">​</a></h2>
<h3 class="anchor anchorWithStickyNavbar_I2Xo" id="使用预置模板">使用预置模板<a href="https://realfuture.ai/blog/2025/06/25/#%E4%BD%BF%E7%94%A8%E9%A2%84%E7%BD%AE%E6%A8%A1%E6%9D%BF" class="hash-link" aria-label="Direct link to 使用预置模板" title="Direct link to 使用预置模板">​</a></h3>
<p>进入"<strong>作业开发</strong>"模块，选择 <code>demo_cdc</code> 草稿：</p>
<div data-rmiz=""><div data-rmiz-content="not-found" style="visibility:visible"><img src="https://realfuture.ai/img/blog/2025-06-25/demo-cdc.png" alt="demo-cdc" style="cursor:pointer"></div></div>
<h3 class="anchor anchorWithStickyNavbar_I2Xo" id="作业内容">作业内容<a href="https://realfuture.ai/blog/2025/06/25/#%E4%BD%9C%E4%B8%9A%E5%86%85%E5%AE%B9" class="hash-link" aria-label="Direct link to 作业内容" title="Direct link to 作业内容">​</a></h3>
<div class="language-yaml codeBlockContainer_eR_5 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_jz8P"><pre tabindex="0" class="prism-code language-yaml codeBlock_tQzK thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_J4lo"><span class="token-line" style="color:#F8F8F2"><span class="token comment" style="color:rgb(98, 114, 164)"># 定义源端，同步内容为 db_test 数据库的所有表结构及表数据</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token key atrule">source</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token key atrule">type</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> mysql</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token key atrule">name</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> source_mysql</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token key atrule">hostname</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> localhost</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token key atrule">password</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> root</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token key atrule">username</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> root</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token key atrule">tables</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> db_test.\.*</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token key atrule">server-time-zone</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> UTC</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token key atrule">server-id</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> 5400</span><span class="token punctuation" style="color:rgb(248, 248, 242)">-</span><span class="token number">5404</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token comment" style="color:rgb(98, 114, 164)"># 定义 doris 目标端，单机版注意设置 replication_num 副本数量为 1</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token key atrule">sink</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token key atrule">type</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> doris</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token key atrule">name</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> sink_doris</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token key atrule">fenodes</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> 127.0.0.1</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token number">8030</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token key atrule">username</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> root</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token key atrule">password</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">""</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token key atrule">table.create.properties.replication_num</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> </span><span class="token number">1</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token key atrule">pipeline</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token key atrule">name</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> demo_cdc</span><br></span></code></pre><div class="buttonGroup_EiCC"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_azoe" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_HjTd"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_dSkr"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<h2 class="anchor anchorWithStickyNavbar_I2Xo" id="作业发布">作业发布<a href="https://realfuture.ai/blog/2025/06/25/#%E4%BD%9C%E4%B8%9A%E5%8F%91%E5%B8%83" class="hash-link" aria-label="Direct link to 作业发布" title="Direct link to 作业发布">​</a></h2>
<h3 class="anchor anchorWithStickyNavbar_I2Xo" id="发布准备">发布准备<a href="https://realfuture.ai/blog/2025/06/25/#%E5%8F%91%E5%B8%83%E5%87%86%E5%A4%87" class="hash-link" aria-label="Direct link to 发布准备" title="Direct link to 发布准备">​</a></h3>
<p>如果按照本教程安装与配置，你无需修改任何内容，点击"<strong>上线</strong>"按钮，提示需要选择 <strong>Flink环境</strong>，如下图所示：</p>
<div data-rmiz=""><div data-rmiz-content="not-found" style="visibility:visible"><img src="https://realfuture.ai/img/blog/2025-06-25/job-dev-cdc-error-tips.png" alt="job-dev-cdc-error-tips" style="cursor:pointer"></div></div>
<p><strong>配置环境</strong>：</p>
<ul>
<li>Flink版本：flink-1.19.1（系统预置）</li>
<li>部署模式：Kubernetes Application</li>
</ul>
<h3 class="anchor anchorWithStickyNavbar_I2Xo" id="发布验证">发布验证<a href="https://realfuture.ai/blog/2025/06/25/#%E5%8F%91%E5%B8%83%E9%AA%8C%E8%AF%81" class="hash-link" aria-label="Direct link to 发布验证" title="Direct link to 发布验证">​</a></h3>
<p>成功发布后将显示如下提示，并提示跳转至运维中心：</p>
<div data-rmiz=""><div data-rmiz-content="not-found" style="visibility:visible"><img src="https://realfuture.ai/img/blog/2025-06-25/job-draft-cdc-release.png" alt="job-draft-cdc-release" style="cursor:pointer"></div></div>
<h2 class="anchor anchorWithStickyNavbar_I2Xo" id="作业运维">作业运维<a href="https://realfuture.ai/blog/2025/06/25/#%E4%BD%9C%E4%B8%9A%E8%BF%90%E7%BB%B4" class="hash-link" aria-label="Direct link to 作业运维" title="Direct link to 作业运维">​</a></h2>
<h3 class="anchor anchorWithStickyNavbar_I2Xo" id="启动作业">启动作业<a href="https://realfuture.ai/blog/2025/06/25/#%E5%90%AF%E5%8A%A8%E4%BD%9C%E4%B8%9A" class="hash-link" aria-label="Direct link to 启动作业" title="Direct link to 启动作业">​</a></h3>
<p>进入到作业运维，可以看到列表已经有了已上线的 <strong>demo_cdc</strong> 草稿，点击操作栏的启动按钮：</p>
<div data-rmiz=""><div data-rmiz-content="not-found" style="visibility:visible"><img src="https://realfuture.ai/img/blog/2025-06-25/start-cdc-job.png" alt="start-cdc-job" style="cursor:pointer"></div></div>
<h3 class="anchor anchorWithStickyNavbar_I2Xo" id="状态监控">状态监控<a href="https://realfuture.ai/blog/2025/06/25/#%E7%8A%B6%E6%80%81%E7%9B%91%E6%8E%A7" class="hash-link" aria-label="Direct link to 状态监控" title="Direct link to 状态监控">​</a></h3>
<p>成功启动后可见 <code>Doris Playgroud</code> 已经同步好 <code>db_test</code> 数据库的表结构和表数据了：</p>
<div data-rmiz=""><div data-rmiz-content="not-found" style="visibility:visible"><img src="https://realfuture.ai/img/blog/2025-06-25/doris-sync-success.png" alt="doris-sync-success" style="cursor:pointer"></div></div>
<p>同时在作业运维也可以看到：</p>
<ul>
<li>实时运行指标面板</li>
<li>资源使用情况（<code>JobManager</code>/<code>TaskManager</code> 内存、可用作业槽等）</li>
<li>作业运行状态</li>
</ul>
<div data-rmiz=""><div data-rmiz-content="not-found" style="visibility:visible"><img src="https://realfuture.ai/img/blog/2025-06-25/start-cdc-job-success.png" alt="start-cdc-job-success" style="cursor:pointer"></div></div>
<p>也可以点击作业名称，进入到详情查看作业的部署信息、作业状态、作业监控、作业日志等信息。</p>
<div data-rmiz=""><div data-rmiz-content="not-found" style="visibility:visible"><img src="https://realfuture.ai/img/blog/2025-06-25/job-operation-cdc-detail.png" alt="job-operation-cdc-detail" style="cursor:pointer"></div></div>
<h2 class="anchor anchorWithStickyNavbar_I2Xo" id="文末总结">文末总结<a href="https://realfuture.ai/blog/2025/06/25/#%E6%96%87%E6%9C%AB%E6%80%BB%E7%BB%93" class="hash-link" aria-label="Direct link to 文末总结" title="Direct link to 文末总结">​</a></h2>
<p>在本次教程中，我们通过 Awestream 平台，用约 5 分钟完成了从 MySQL 到 Doris 的实时数据同步配置。整个过程无需复杂编码，通过简单配置即可实现高效、稳定的企业级数据同步。</p>
<h3 class="anchor anchorWithStickyNavbar_I2Xo" id="核心收获">核心收获<a href="https://realfuture.ai/blog/2025/06/25/#%E6%A0%B8%E5%BF%83%E6%94%B6%E8%8E%B7" class="hash-link" aria-label="Direct link to 核心收获" title="Direct link to 核心收获">​</a></h3>
<ol>
<li>极速搭建环境：借助 Docker 快速部署 MySQL 和 Doris，降低学习成本，100% 可复现。</li>
<li>零代码开发：Awestream 提供开箱即用的 CDC 模板，像填写表格一样完成数据同步配置。</li>
<li>一键上线 &amp; 智能运维：15秒完成作业部署，可视化监控、日志回溯、自动扩缩容，运维无忧。</li>
<li>实时同步验证：数据变更秒级同步，确保 Doris 与 MySQL 数据强一致，满足业务需求。</li>
</ol>
<h3 class="anchor anchorWithStickyNavbar_I2Xo" id="awestream-的独特优势">Awestream 的独特优势<a href="https://realfuture.ai/blog/2025/06/25/#awestream-%E7%9A%84%E7%8B%AC%E7%89%B9%E4%BC%98%E5%8A%BF" class="hash-link" aria-label="Direct link to Awestream 的独特优势" title="Direct link to Awestream 的独特优势">​</a></h3>
<ol>
<li>低门槛：即使没有大数据经验，也能轻松上手。</li>
<li>高效率：简化传统流式计算流程，约 5 分钟完成企业级同步配置。</li>
<li>可观测性：全链路监控，实时掌握作业运行状态，问题排查更便捷。</li>
</ol>
<h3 class="anchor anchorWithStickyNavbar_I2Xo" id="适用场景">适用场景<a href="https://realfuture.ai/blog/2025/06/25/#%E9%80%82%E7%94%A8%E5%9C%BA%E6%99%AF" class="hash-link" aria-label="Direct link to 适用场景" title="Direct link to 适用场景">​</a></h3>
<ol>
<li>📌 实时数据分析（如运营大盘、风控监控）</li>
<li>📌 数据湖仓建设（MySQL→Doris/Hudi/Iceberg）</li>
<li>📌 业务系统数据同步（多数据库异构同步）</li>
</ol>
<p>🚀 现在就用 Awestream，让你的实时数据同步变得前所未有的简单</p>]]></content:encoded>
            <category>Realfuture</category>
            <category>Engineering</category>
        </item>
        <item>
            <title><![CDATA[Flink on Kubernetes 自动弹性扩缩容实践]]></title>
            <link>https://realfuture.ai/blog/2025/06/24/</link>
            <guid>https://realfuture.ai/blog/2025/06/24/</guid>
            <pubDate>Tue, 24 Jun 2025 00:00:00 GMT</pubDate>
            <description><![CDATA[本文演示如何在 Kubernetes 环境下，基于 TaskManager 实例的资源使用情况，实现 Flink 作业的自动弹性扩缩容。]]></description>
            <content:encoded><![CDATA[<p>本文演示如何在 <code>Kubernetes</code> 环境下，基于 <code>TaskManager</code> 实例的资源使用情况，实现 <code>Flink</code> 作业的自动弹性扩缩容。</p>
<!-- -->
<h2 class="anchor anchorWithStickyNavbar_I2Xo" id="新建作业">新建作业<a href="https://realfuture.ai/blog/2025/06/24/#%E6%96%B0%E5%BB%BA%E4%BD%9C%E4%B8%9A" class="hash-link" aria-label="Direct link to 新建作业" title="Direct link to 新建作业">​</a></h2>
<p>在作业开发页面新建作业草稿，或直接使用内置的 <code>demo_jar</code> 作业，依次选择“<code>Flink</code> 版本” → “<code>Kubernetes Application</code> 模式”：</p>
<div data-rmiz=""><div data-rmiz-content="not-found" style="visibility:visible"><img src="https://realfuture.ai/img/blog/2025-06-24/autoscaler_demo_jar.png" alt="autoscaler_demo_jar" style="cursor:pointer"></div></div>
<h2 class="anchor anchorWithStickyNavbar_I2Xo" id="扩缩容配置">扩缩容配置<a href="https://realfuture.ai/blog/2025/06/24/#%E6%89%A9%E7%BC%A9%E5%AE%B9%E9%85%8D%E7%BD%AE" class="hash-link" aria-label="Direct link to 扩缩容配置" title="Direct link to 扩缩容配置">​</a></h2>
<h3 class="anchor anchorWithStickyNavbar_I2Xo" id="作业并行度及-cpu-配额限制">作业并行度及 CPU 配额限制<a href="https://realfuture.ai/blog/2025/06/24/#%E4%BD%9C%E4%B8%9A%E5%B9%B6%E8%A1%8C%E5%BA%A6%E5%8F%8A-cpu-%E9%85%8D%E9%A2%9D%E9%99%90%E5%88%B6" class="hash-link" aria-label="Direct link to 作业并行度及 CPU 配额限制" title="Direct link to 作业并行度及 CPU 配额限制">​</a></h3>
<p>点击右侧配置栏的 <code>Flink</code> 按钮，展开后，配置并行度为 10，单个 <code>TaskManager CPU</code> 配额：1 核（1000m）:</p>
<div data-rmiz=""><div data-rmiz-content="not-found" style="visibility:visible"><img src="https://realfuture.ai/img/blog/2025-06-24/autoscaler_flink_config.png" alt="autoscaler_flink_config" style="cursor:pointer"></div></div>
<h3 class="anchor anchorWithStickyNavbar_I2Xo" id="配置扩缩容条件">配置扩缩容条件<a href="https://realfuture.ai/blog/2025/06/24/#%E9%85%8D%E7%BD%AE%E6%89%A9%E7%BC%A9%E5%AE%B9%E6%9D%A1%E4%BB%B6" class="hash-link" aria-label="Direct link to 配置扩缩容条件" title="Direct link to 配置扩缩容条件">​</a></h3>
<p>点击右侧配置栏的 <code>kubernetes</code> 按钮，打开<strong>弹性扩缩容</strong>开关，可以看到配置如下：</p>
<div data-rmiz=""><div data-rmiz-content="not-found" style="visibility:visible"><img src="https://realfuture.ai/img/blog/2025-06-24/autoscaler_config.png" alt="autoscaler_config" style="cursor:pointer"></div></div>
<p>其中的扩缩容条件，支持如下几种：</p>
<table><thead><tr><th>类型</th><th>备注</th></tr></thead><tbody><tr><td><strong>CPU</strong></td><td>根据 <code>TaskManager CPU</code> 利用率动态调整实例数量</td></tr><tr><td><strong>内存</strong></td><td>根据 <code>TaskManager</code> 内存利用率动态调整实例数量</td></tr><tr><td><strong>CPU和内存</strong></td><td>同时根据 <code>CPU</code> 和内存利用率动态调整</td></tr><tr><td><strong>自定义规则</strong></td><td>支持基于自定义 <code>Flink</code> 指标（如 <code>backlog</code>、延迟、<code>Watermark</code> 滞后等）扩缩容</td></tr></tbody></table>
<p>如上图所示，这里设置为 <strong>基于 <code>CPU</code> 作为扩缩容条件，当 <code>CPU</code> 百分比大于 65%，<code>TaskManager</code> 会进行自动扩缩容，副本数最小为 1，最大不能超过 5</strong>。</p>
<h2 class="anchor anchorWithStickyNavbar_I2Xo" id="上线启动作业">上线启动作业<a href="https://realfuture.ai/blog/2025/06/24/#%E4%B8%8A%E7%BA%BF%E5%90%AF%E5%8A%A8%E4%BD%9C%E4%B8%9A" class="hash-link" aria-label="Direct link to 上线启动作业" title="Direct link to 上线启动作业">​</a></h2>
<p>继续点击作业上线，直至上线成功：</p>
<div data-rmiz=""><div data-rmiz-content="not-found" style="visibility:visible"><img src="https://realfuture.ai/img/blog/2025-06-24/autoscaler_job_release.png" alt="autoscaler_job_release" style="cursor:pointer"></div></div>
<p>跳转至作业运维中心，点击启动按钮启动作业：</p>
<div data-rmiz=""><div data-rmiz-content="not-found" style="visibility:visible"><img src="https://realfuture.ai/img/blog/2025-06-24/autoscaler_job_start.png" alt="autoscaler_job_start" style="cursor:pointer"></div></div>
<p>作业运行成功：</p>
<div data-rmiz=""><div data-rmiz-content="not-found" style="visibility:visible"><img src="https://realfuture.ai/img/blog/2025-06-24/autoscaler_job_run_success.png" alt="autoscaler_job_run_success" style="cursor:pointer"></div></div>
<p>进入 "<strong>作业详情 → 作业状态</strong>"，点击 “<code>Apache Flink UI</code>”，可以看到当前作业运行正常，且 tasks 总数量以及运行中的数量均为2：</p>
<div data-rmiz=""><div data-rmiz-content="not-found" style="visibility:visible"><img src="https://realfuture.ai/img/blog/2025-06-24/autoscaler_flink_job.png" alt="autoscaler_flink_job" style="cursor:pointer"></div></div>
<p>为了方便讲解，这里使用 <code>kubernetes-dashboard</code> 继续查看作业部署的部署情况，如下图：</p>
<div data-rmiz=""><div data-rmiz-content="not-found" style="visibility:visible"><img src="https://realfuture.ai/img/blog/2025-06-24/autoscaler_job_pods.png" alt="autoscaler_job_pods" style="cursor:pointer"></div></div>
<p>从图中可以看出:</p>
<ul>
<li>作业部署到了 "<strong>realfuture-jobs-streampark-100000</strong>" 空间，这个空间会自动创建，格式一般为："<u><strong>realfuture-jobs-空间名-空间ID</strong></u>"。</li>
<li>作业分为了两个 <code>JobManager</code> 和 <code>TaskManager pod</code>，且都只有一个副本。</li>
<li><code>TaskManager</code> 的 <code>CPU</code> 资源利用率也不高，只有 <code>27.00m</code>。</li>
</ul>
<p>当然也可以通过命令查看资源使用率情况情况：</p>
<div class="codeBlockContainer_eR_5 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_jz8P"><pre tabindex="0" class="prism-code language-text codeBlock_tQzK thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_J4lo"><span class="token-line" style="color:#F8F8F2"><span class="token plain">kubectl get hpa -A</span><br></span></code></pre><div class="buttonGroup_EiCC"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_azoe" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_HjTd"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_dSkr"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<div data-rmiz=""><div data-rmiz-content="not-found" style="visibility:visible"><img src="https://realfuture.ai/img/blog/2025-06-24/autoscaler_job_cpu_usages.png" alt="autoscaler_job_cpu_usages" style="cursor:pointer"></div></div>
<p>从图中可以看到目前 <code>TaskManager</code> 的资源使用率仅为 2%。</p>
<p>接下来尝试人为对 <code>CPU</code> 进行暴力增压，使其 <code>CPU</code> 飙升。</p>
<h2 class="anchor anchorWithStickyNavbar_I2Xo" id="模拟-cpu-飙升">模拟 CPU 飙升<a href="https://realfuture.ai/blog/2025/06/24/#%E6%A8%A1%E6%8B%9F-cpu-%E9%A3%99%E5%8D%87" class="hash-link" aria-label="Direct link to 模拟 CPU 飙升" title="Direct link to 模拟 CPU 飙升">​</a></h2>
<p>这里写了一个脚本，模拟使 <code>TaskManager pod</code> 的使用率飙升，核心方法如下：</p>
<div class="language-shell codeBlockContainer_eR_5 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_jz8P"><pre tabindex="0" class="prism-code language-shell codeBlock_tQzK thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_J4lo"><span class="token-line" style="color:#F8F8F2"><span class="token plain">start_load() {</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  if kubectl get pod load-generator -n realfuture-jobs-streampark-100000 &amp;&gt; /dev/null; then</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    echo "Load generator is already running."</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  else</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    echo "Starting load generator..."</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    kubectl run load-generator --image=busybox --restart=Never --namespace=realfuture-jobs-streampark-100000 --image-pull-policy=IfNotPresent -- /bin/sh -c "</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    for i in \$(seq 1 20); do</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">      while true; do wget -q -O- http://taskmanager-100000:9249/metrics; done &amp;</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    done</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    wait</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    "</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  fi</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">}</span><br></span></code></pre><div class="buttonGroup_EiCC"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_azoe" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_HjTd"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_dSkr"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>该方法的逻辑是不断地去请求 <code>TaskManager pod</code>，使其 <code>CPU</code> 不断地飙升，运行该方法前，可以看到作业情况如下：</p>
<div data-rmiz=""><div data-rmiz-content="not-found" style="visibility:visible"><img src="https://realfuture.ai/img/blog/2025-06-24/autoscaler_stress_before.png" alt="autoscaler_stress_before" style="cursor:pointer"></div></div>
<h2 class="anchor anchorWithStickyNavbar_I2Xo" id="自动扩容">自动扩容<a href="https://realfuture.ai/blog/2025/06/24/#%E8%87%AA%E5%8A%A8%E6%89%A9%E5%AE%B9" class="hash-link" aria-label="Direct link to 自动扩容" title="Direct link to 自动扩容">​</a></h2>
<p>运行一段时间后，可以看到 <code>TaskManager</code> 的 <code>CPU</code> 从 22m 飙升到了 778m：</p>
<div data-rmiz=""><div data-rmiz-content="not-found" style="visibility:visible"><img src="https://realfuture.ai/img/blog/2025-06-24/autoscaler_stress_cpu_high.png" alt="autoscaler_stress_cpu_high" style="cursor:pointer"></div></div>
<p>通过运行命令，也可以看到 <code>CPU</code> 占用率为 87% ，远超设定的 65% 的阈值：</p>
<div data-rmiz=""><div data-rmiz-content="not-found" style="visibility:visible"><img src="https://realfuture.ai/img/blog/2025-06-24/autoscaler_stress_hpa.png" alt="autoscaler_stress_hpa" style="cursor:pointer"></div></div>
<p>这个时候，通过 <code>kubernetes-dashboard</code> 可以看到 <code>TaskManager</code> 的自动扩容多了一个副本：</p>
<div data-rmiz=""><div data-rmiz-content="not-found" style="visibility:visible"><img src="https://realfuture.ai/img/blog/2025-06-24/autoscaler_tm_pod_add.png" alt="autoscaler_tm_pod_add" style="cursor:pointer"></div></div>
<p>在 <code>Flink Web UI</code> 也可以看到，<strong>TaskManager</strong> 自动增加了一个：</p>
<div data-rmiz=""><div data-rmiz-content="not-found" style="visibility:visible"><img src="https://realfuture.ai/img/blog/2025-06-24/autoscaler_flink_web_tm.png" alt="autoscaler_flink_web_tm" style="cursor:pointer"></div></div>
<p>任务数也从 2 变为了 3，作业自动重启。</p>
<div data-rmiz=""><div data-rmiz-content="not-found" style="visibility:visible"><img src="https://realfuture.ai/img/blog/2025-06-24/autoscaler_tasks_incress.png" alt="autoscaler_tasks_incress" style="cursor:pointer"></div></div>
<p>在此返回作业运维中心，可以看到作业稳定运行，全程无需人工干预：</p>
<div data-rmiz=""><div data-rmiz-content="not-found" style="visibility:visible"><img src="https://realfuture.ai/img/blog/2025-06-24/autoscaler_job_operation.png" alt="autoscaler_job_operation" style="cursor:pointer"></div></div>
<h2 class="anchor anchorWithStickyNavbar_I2Xo" id="自动缩容">自动缩容<a href="https://realfuture.ai/blog/2025/06/24/#%E8%87%AA%E5%8A%A8%E7%BC%A9%E5%AE%B9" class="hash-link" aria-label="Direct link to 自动缩容" title="Direct link to 自动缩容">​</a></h2>
<p>执行停止脚本，模拟 <code>CPU</code> 下降，模拟脚本如下：</p>
<div class="language-shell codeBlockContainer_eR_5 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_jz8P"><pre tabindex="0" class="prism-code language-shell codeBlock_tQzK thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_J4lo"><span class="token-line" style="color:#F8F8F2"><span class="token plain">stop_load() {</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  if kubectl get pod load-generator -n realfuture-jobs-streampark-100000 &amp;&gt; /dev/null; then</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    echo "Stopping load generator..."</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    kubectl delete pod load-generator -n realfuture-jobs-streampark-100000</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  else</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    echo "No load generator running."</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  fi</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">}</span><br></span></code></pre><div class="buttonGroup_EiCC"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_azoe" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_HjTd"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_dSkr"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>大约 5 分钟后，<code>TaskManager</code> 会自动缩容，副本数减少 1：</p>
<div data-rmiz=""><div data-rmiz-content="not-found" style="visibility:visible"><img src="https://realfuture.ai/img/blog/2025-06-24/autoscaler_tm_pod_sub.png" alt="autoscaler_tm_pod_sub" style="cursor:pointer"></div></div>
<h2 class="anchor anchorWithStickyNavbar_I2Xo" id="总结">总结<a href="https://realfuture.ai/blog/2025/06/24/#%E6%80%BB%E7%BB%93" class="hash-link" aria-label="Direct link to 总结" title="Direct link to 总结">​</a></h2>
<p>通过本实践可以验证：</p>
<ul>
<li><code>Flink</code> 作业在 <code>Kubernetes</code> 环境下，基于 <code>TaskManager</code> 资源利用率，能够动态实现自动扩缩容，保障作业在负载波动场景下的稳定运行。</li>
<li>支持多维度扩缩容策略，如 <code>CPU</code> 利用率、内存使用率、以及自定义 <code>Flink</code> 指标（如 <code>backlog</code>、延迟、<code>Watermark</code> 滞后等），满足不同业务场景的资源弹性调度需求。</li>
<li>全流程无需人工干预，作业能够根据实时负载自动扩容或缩容，有效提升资源利用效率与作业稳定性。</li>
<li>提供 <code>Flink Web UI</code>、<code>kubernetes-dashboard</code> 以及 <code>kubectl</code> 命令行工具，多维度监控与运维手段，便于作业运行状态的实时观测与管理。</li>
</ul>
<p>这是一种简单、高效、可落地的 Flink 作业自动弹性扩缩容最佳实践，值得在实际生产环境中推广应用。</p>]]></content:encoded>
            <category>Realfuture</category>
            <category>Engineering</category>
        </item>
        <item>
            <title><![CDATA[Apache StreamPark 毕业成为 Apache 顶级项目]]></title>
            <link>https://realfuture.ai/blog/2025/02/28/</link>
            <guid>https://realfuture.ai/blog/2025/02/28/</guid>
            <pubDate>Fri, 28 Feb 2025 00:00:00 GMT</pubDate>
            <description><![CDATA[Apache StreamPark 正式从 Apache 孵化器毕业，成为 Apache 软件基金会顶级项目（Top-Level Project，TLP）。]]></description>
            <content:encoded><![CDATA[<p>北京时间 2025 年 1 月 28 日，Apache Software Foundation（以下简称 ASF）发布公告：Apache StreamPark 正式从 Apache 孵化器毕业，成为 Apache 软件基金会顶级项目（Top-Level Project，TLP）。这一里程碑表明 StreamPark 在技术质量、社区治理和可持续发展等方面获得了 ASF 的认可。</p>
<div data-rmiz=""><div data-rmiz-content="not-found" style="visibility:visible"><img src="https://realfuture.ai/img/blog/2025-02-28/asf_blog.jpg" alt="asf_blog" style="cursor:pointer"></div></div>
<!-- -->
<h2 class="anchor anchorWithStickyNavbar_I2Xo" id="关于-streampark">关于 StreamPark<a href="https://realfuture.ai/blog/2025/02/28/#%E5%85%B3%E4%BA%8E-streampark" class="hash-link" aria-label="Direct link to 关于 StreamPark" title="Direct link to 关于 StreamPark">​</a></h2>
<p>Apache StreamPark 是一款流应用程序开发管理框架：为 Apache Flink &amp; Apache Spark 提供了一套快速开发作业的框架和一站式流作业管理平台。</p>
<div data-rmiz=""><div data-rmiz-content="not-found" style="visibility:visible"><img src="https://realfuture.ai/img/blog/2025-02-28/streampark_dashboard.jpg" alt="streampark_dashboard" style="cursor:pointer"></div></div>
<p>其核心特性和优势包括：</p>
<p><strong>流作业开发脚手架：</strong> StreamPark 提供了流作业开发的脚手架，旨在简化 Flink 和 Spark 作业开发流程。它摒弃了传统繁琐的开发模式，低代码实现复杂流处理逻辑，将作业配置与核心业务逻辑分离，提供了快捷的API 和一套即插即用的连接器，显著降低了用户学习和开发流作业的复杂度，让流作业开发更加高效便捷。</p>
<p><strong>专业的流作业管理能力：</strong> StreamPark 以其卓越的流作业管理能力著称，提供了一站式流作业管理平台，涵盖从开发构建、部署上线、状态管理与恢复到操作运维的全生命周期支持，简化了作业部署到不同集群的复杂性，使 Flink 和 Spark 作业能够轻松部署在 YARN 和 Kubernetes 上。此外，StreamPark 具备秒级作业状态同步、实时监控以及告警通知能力，有效保障了系统的稳定性，为平台的持续发展奠定了坚实基础。</p>
<p><strong>简单易用，流计算开发体验创新者</strong> ：StreamPark 在流计算作业开发和平台功能上不断探索和创新，既支持流计算引擎 Flink，又支持微批处理引擎 Spark，真正实现了流批一体化融合，成为业界首个在同一平台上兼容多引擎、多版本的工具。在使用体验上不断引入新功能，致力于降低用户的学习和使用门槛，即使是初学者也能在几分钟内快速上手。这种极简的开发体验，为 Apache Flink 和 Spark 的落地与推广做出了贡献，让更多企业和开发者能够轻松驾驭实时计算技术，释放数据价值。</p>
<p><strong>全面生态集成和拓展</strong> ：StreamPark 已经与众多开源工具和技术栈实现了深度集成，支持包括 Flink、Spark、Paimon、Doris、Flink CDC 等在内的诸多生态开源项目。无论是实时作业的开发管理，还是实时数据集成需求，StreamPark 都能轻松应对，为用户提供了一站式的解决方案。这种强大的生态兼容性不仅简化了开发流程，还为用户提供了更灵活的技术选择，助力企业快速构建高效、稳定的实时数据处理平台。</p>
<h2 class="anchor anchorWithStickyNavbar_I2Xo" id="成长历程">成长历程<a href="https://realfuture.ai/blog/2025/02/28/#%E6%88%90%E9%95%BF%E5%8E%86%E7%A8%8B" class="hash-link" aria-label="Direct link to 成长历程" title="Direct link to 成长历程">​</a></h2>
<p>Apache StreamPark 原名 StreamX，由个人开发者 <strong>王华杰</strong> 开发并于 2021 年 4 月开源，初衷是让流处理更简单，希望解决实时计算 Flink &amp; Spark 作业开发复杂和运维困难的问题，给用户提供一个简单易用的流作业开发框架和管控平台。</p>
<p><strong>2022 年 9 月 1 日</strong>，StreamX 项目顺利通过投票，正式进入 Apache 软件基金会 (ASF) 的孵化器，改名为 Apache StreamPark，这也是首个个人捐赠到 Apache 基金会的大数据项目。之后在导师 tison、Willem Ning Jiang、Duo Zhang、Stephan Ewen、Thomas Weise 的指导下，由孵化器管理委员会成员进行辅导和孵化。</p>
<p><strong>2025 年 1 月 23 日</strong>，Apache 董事会通过 Apache StreamPark 毕业决议，项目结束了为期 27 个月的孵化并成为 Apache 顶级项目。</p>
<p><strong>在社区发展方面</strong>，Apache StreamPark 在 ASF 孵化期间累计发布了 7 个 Apache 版本，创建 2500+ 个 PR，合并 2400+ 个 PR。文章发布时，StreamPark 在 GitHub 上拥有 4K+ Star，社区规模达到 5000+ 人，贡献者超过 150 人，并新增了 8 位 Committer 和 2 位 PMC 成员。</p>
<div data-rmiz=""><div data-rmiz-content="not-found" style="visibility:visible"><img src="https://realfuture.ai/img/blog/2025-02-28/contributors.jpg" alt="contributors" style="cursor:pointer"></div></div>
<p><strong>在用户群体方面</strong>，Apache StreamPark 现已广泛应用于互联网、金融、零售、出行、智能家居、云服务、游戏等各行各业中，更有如：火山引擎、百度、腾讯、中国联通、天翼云、马蜂窝、长安汽车 等各行业头部大公司使用，金融行业有：杭州银行、桂林银行、天津银行、汇丰金融 等落地实践。 在实时计算、实时风控、数据清洗、实时数据同步等诸多应用场景中，可方便快捷地管理大规模实时作业。</p>
<div data-rmiz=""><div data-rmiz-content="not-found" style="visibility:visible"><img src="https://realfuture.ai/img/blog/2025-02-28/users.jpg" alt="users" style="cursor:pointer"></div></div>
<p>在过去的 27 个月孵化期内，Apache StreamPark 取得了显著的进步，其发展成果有目共睹。社区规模持续扩大，社群活跃度不断提升，项目知名度日益提高，吸引了来自各行各业的众多用户。同时，在孵化期间 StreamPark 多次登上 GitHub Trending 榜单，多次获得业内荣誉，这些成就无不彰显着项目快速发展的势头和无限的潜力。</p>
<ul>
<li><strong>2022 中国互联网发展创新与投资大赛二等奖</strong></li>
<li><strong>2022 OSC 开源中国「中国开源社区健康案例」</strong></li>
<li><strong>2023 OSC 开源中国「中国开源社区健康案例」</strong></li>
<li><strong>2023 OSC 开源中国「年度优秀开源技术团队」</strong></li>
<li><strong>2023 开放原子开源基金会「快速成长开源项目」</strong></li>
<li><strong>2024 中国互联网发展创新与投资大赛二等奖</strong></li>
<li><strong>2024 年开源创新榜单「年度开源项目」</strong></li>
</ul>
<div data-rmiz=""><div data-rmiz-content="not-found" style="visibility:visible"><img src="https://realfuture.ai/img/blog/2025-02-28/trending.jpg" alt="trending" style="cursor:pointer"></div></div>
<p>毕业成为 Apache 顶级项目对  StreamPark 意义重大。ASF 的顶级项目需通过社区共识和专家评审，代表项目在技术质量、社区治理和可持续性方面已趋成熟。StreamPark 的成功毕业是对社区努力和创新精神的认可，标志着其在项目合规、社区治理、代码质量、用户采用度等方面达到了 Apache 的严格标准。这将进一步加速项目的普及与应用，推动项目在全球范围内的快速健康发展。</p>
<h2 class="anchor anchorWithStickyNavbar_I2Xo" id="特别感谢">特别感谢<a href="https://realfuture.ai/blog/2025/02/28/#%E7%89%B9%E5%88%AB%E6%84%9F%E8%B0%A2" class="hash-link" aria-label="Direct link to 特别感谢" title="Direct link to 特别感谢">​</a></h2>
<p>StreamPark 能顺利毕业成为 Apache 顶级项目，离不开社区的帮助和支持，特别感谢项目的 Champion @tison 将项目带入到 ASF，带来一段美好的旅程，并在整个孵化过程中给予了无私的帮助和指导。</p>
<p>特别感谢项目导师 @姜宁、@张铎 在整个孵化项目过程中给予了专业指导和大力帮助，推进了项目的顺利毕业。</p>
<p>感谢导师 @Stephan Ewen、@Thomas Weise 两位导师对项目的认可和帮助，感谢 @Kent Yao、@李岗，多次在项目发版过程中认真检查项目合规，使得发版过程顺利进行。</p>
<p>特别感谢友邻社区 @Apache Flink 社区、@Apache Doris 社区、@ALC Beijing、@OSC 开源中国 等社区对 Apache StreamPark 社区的帮助和支持。</p>
<p>感谢各大媒体、社区及行业同仁在技术领域传播这一振奋人心的消息(排名不分前后)： @ITPUB、@DataFun、@OSC 开源中国、@InfoQ 、@CSDN、@ALC北京、@夜天之书</p>
<p>我们衷心感谢所有为 StreamPark 做出贡献的开发者、用户和合作伙伴。是大家的支持和信任，让 Apache StreamPark 顺利毕业，毕业不是终点，而是 Apache StreamPark 的全新起点！在此我们也诚挚邀请更多志同道合的朋友加入 StreamPark 社区，我们将秉承更加兼容并包的心态，迎接更多的机遇与挑战，用代码点燃数据流的璀璨烟花，共同谱写实时数据流技术的未来篇章！</p>
<ul>
<li><strong>项目地址：</strong> <a href="https://github.com/apache/streampark" target="_blank" rel="noopener noreferrer">https://github.com/apache/streampark</a></li>
<li><strong>提交问题和建议：</strong> <a href="https://github.com/apache/streampark/issues" target="_blank" rel="noopener noreferrer">https://github.com/apache/streampark/issues</a></li>
<li><strong>贡献代码：</strong> <a href="https://github.com/apache/streampark/pulls" target="_blank" rel="noopener noreferrer">https://github.com/apache/streampark/pulls</a></li>
<li><strong>Proposal：</strong> <a href="https://cwiki.apache.org/confluence/display/INCUBATOR/StreamPark+Proposal" target="_blank" rel="noopener noreferrer">https://cwiki.apache.org/confluence/display/INCUBATOR/StreamPark+Proposal</a></li>
<li><strong>订阅社区开发邮件列表：</strong> <a href="mailto:dev@streampark.apache.org" target="_blank" rel="noopener noreferrer">dev@streampark.apache.org</a></li>
</ul>]]></content:encoded>
            <category>StreamPark</category>
        </item>
        <item>
            <title><![CDATA[Apache StreamPark 入选“2024 开源创新榜单·年度开源项目”]]></title>
            <link>https://realfuture.ai/blog/2024/12/20/</link>
            <guid>https://realfuture.ai/blog/2024/12/20/</guid>
            <pubDate>Fri, 20 Dec 2024 00:00:00 GMT</pubDate>
            <description><![CDATA[Apache StreamPark 凭借持续的开源贡献与项目价值，入选“2024 开源创新榜单·年度开源项目”。]]></description>
            <content:encoded><![CDATA[<p>2024 年 12 月 16 日，在国家科技传播中心举行的重大科技成就发布会上，Apache StreamPark 凭借持续的开源贡献和项目价值，经评审入选“2024 年度开源项目”。评选结果已在国家科技传播中心官网公布。</p>
<div data-rmiz=""><div data-rmiz-content="not-found" style="visibility:visible"><img src="https://realfuture.ai/img/blog/2024-12-20/01.png" alt="01" style="cursor:pointer"></div></div>
<!-- -->
<h2 class="anchor anchorWithStickyNavbar_I2Xo" id="2024-年开源创新榜单">2024 年开源创新榜单<a href="https://realfuture.ai/blog/2024/12/20/#2024-%E5%B9%B4%E5%BC%80%E6%BA%90%E5%88%9B%E6%96%B0%E6%A6%9C%E5%8D%95" class="hash-link" aria-label="Direct link to 2024 年开源创新榜单" title="Direct link to 2024 年开源创新榜单">​</a></h2>
<p>「2024 年开源创新榜单」由中国科协科学技术传播中心、中国计算机学会、中国通信学会、中国科学院软件研究所共同主办，中国开发者社区承办，面向中国开源行业领域，遴选具有创新性、 贡献度和影响力的开源项目、社区、应用场景与开源事件，王怀民院士为首组建评审委员会，经研讨评审，评审出 10 个年度开源项目、10 个年度开源社区、10 个年度开源应用场景与 10 大年度开源事件。</p>
<p>“重大科技成就发布会(首场)”活动依托于 2024 年开源创新榜单，旨在致敬中国开源力量，传播推广开源科技成就，营造中国开源创新生态。</p>
<p>在此次发布会上，除了公布包括 StreamPark 上榜的「2024 年开源创新榜单」 之外，还发布了中国算力网开源开放试验场、星辰语义大模型平台和书生大模型等重大科技成果。</p>
<p>这些成果的发布，不仅展示了我国在开源创新领域的最新进展，也为全球开源社区贡献了中国智慧和中国方案。随着这些项目的推进和实施，预计将进一步加速我国科技创新的步伐，为经济社会发展注入新的动力。</p>
<div data-rmiz=""><div data-rmiz-content="not-found" style="visibility:visible"><img src="https://realfuture.ai/img/blog/2024-12-20/02.png" alt="02" style="cursor:pointer"></div></div>
<h2 class="anchor anchorWithStickyNavbar_I2Xo" id="apache-streampark">Apache StreamPark<a href="https://realfuture.ai/blog/2024/12/20/#apache-streampark" class="hash-link" aria-label="Direct link to Apache StreamPark" title="Direct link to Apache StreamPark">​</a></h2>
<p>Apache StreamPark 是一个流处理应用开发与管理框架，旨在简化流处理应用的构建与运维。它为 Apache Flink 和 Apache Spark 提供开发框架与一站式管控平台，核心能力包括应用开发、调试、交互查询、部署和运维等。文章发布时，项目已在天翼云、中国联通、同程数科、马蜂窝、长安汽车、杭州银行和自如等企业的生产环境中使用。</p>
<div data-rmiz=""><div data-rmiz-content="not-found" style="visibility:visible"><img src="https://realfuture.ai/img/blog/2024-12-20/03.png" alt="03" style="cursor:pointer"></div></div>
<h2 class="anchor anchorWithStickyNavbar_I2Xo" id="荣誉加身-步履不停">荣誉加身 步履不停<a href="https://realfuture.ai/blog/2024/12/20/#%E8%8D%A3%E8%AA%89%E5%8A%A0%E8%BA%AB-%E6%AD%A5%E5%B1%A5%E4%B8%8D%E5%81%9C" class="hash-link" aria-label="Direct link to 荣誉加身 步履不停" title="Direct link to 荣誉加身 步履不停">​</a></h2>
<p>Apache StreamPark 作为一个年轻的开源项目，在具有如此权威性和中立性的国家单位指导举办的大赛中，经过角逐获得年度开源项目的奖项，我们深感荣幸，这份荣誉属于社区所有贡献者和一直以来帮助我们的老师们，是对长期以来相信开源，默默贡献开源的开发团队的嘉许和认可，同时也鞭策着我们更加努力的做好项目，建设发展好社区。后续我们将继续保持开发者谦逊朴素的本质，以用户为本，聆听用户的需求，以做好一个项目为原则，秉承更加兼容并包的心态，迎接更多的机遇与挑战，推动中国开源的繁荣发展。</p>]]></content:encoded>
            <category>StreamPark</category>
        </item>
        <item>
            <title><![CDATA[开源人的荣耀时刻：Apache StreamPark 接连获奖]]></title>
            <link>https://realfuture.ai/blog/2024/11/21/</link>
            <guid>https://realfuture.ai/blog/2024/11/21/</guid>
            <pubDate>Thu, 21 Nov 2024 00:00:00 GMT</pubDate>
            <description><![CDATA[Apache StreamPark 项目及核心贡献者在北京举行的多项开源活动中获得表彰。]]></description>
            <content:encoded><![CDATA[<p>近日 Apache StreamPark 项目和核心贡献者在京举行的开源活动中，接连受到表彰，这是项目和社区的荣耀时刻，让我们继续努力，向光而行，更进一步。</p>
<!-- -->
<h2 class="anchor anchorWithStickyNavbar_I2Xo" id="oscar-尖峰开源人物">OSCAR 尖峰开源人物<a href="https://realfuture.ai/blog/2024/11/21/#oscar-%E5%B0%96%E5%B3%B0%E5%BC%80%E6%BA%90%E4%BA%BA%E7%89%A9" class="hash-link" aria-label="Direct link to OSCAR 尖峰开源人物" title="Direct link to OSCAR 尖峰开源人物">​</a></h2>
<p>10 月 16 日，中国通信标准化协会 &amp; 云计算标准和开源推进委员会在北京召开了“OSCAR 开源产业大会”。为推动开源产业发展，树立标杆和典范，特设立了“OSCAR 开源尖峰案例”评选活动，并在大会上公布了评选结果。经过严格筛选，<strong>Apache StreamPark PMC 成员，项目作者王华杰通过在 StreamPark 项目的持续贡献，对用户的大力支持，宣传布道等多方面综合评估，获得评委一致认可，荣获《OSCAR 尖峰开源人物》称号</strong>。</p>
<div data-rmiz=""><div data-rmiz-content="not-found" style="visibility:visible"><img src="https://realfuture.ai/img/blog/2024-11-21/01.png" alt="01" style="cursor:pointer"></div></div>
<p>Apache StreamPark 项目原 StreamX，由项目作者王华杰 2019 年开发，2021 年开源，2022 年 9 月 捐赠给 Apache 基金会的项目，<strong>这是大数据领域首个个人捐赠的项目</strong>，与由公司发起和支持的项目不同，个人主体捐赠的项目不论是在社区建设还是项目发展，人力投入，项目运营等方面往往都更困难一些。</p>
<p><strong>王华杰先生能获得《OSCAR 尖峰开源人物》称号，不仅是对个人的肯定，更是对项目，对中国广大开源项目作者和贡献者的鼓励和肯定。</strong></p>
<h2 class="anchor anchorWithStickyNavbar_I2Xo" id="中国开源创新大赛二等奖">中国开源创新大赛二等奖<a href="https://realfuture.ai/blog/2024/11/21/#%E4%B8%AD%E5%9B%BD%E5%BC%80%E6%BA%90%E5%88%9B%E6%96%B0%E5%A4%A7%E8%B5%9B%E4%BA%8C%E7%AD%89%E5%A5%96" class="hash-link" aria-label="Direct link to 中国开源创新大赛二等奖" title="Direct link to 中国开源创新大赛二等奖">​</a></h2>
<p>11 月 20 日，由中央网信办信息化发展局指导，中国互联网发展基金会、中国网络空间研究院、中国互联网投资基金联合主办，北京初心开源技术有限公司承办的“2024 中国互联网发展创新与投资大赛（开源）”在京举行表彰大会。</p>
<p>Apache StreamPark 项目荣获 <strong>2024 中国开源创新大赛二等奖</strong>，项目多位核心贡献者受到表彰。恭喜项目核心贡献者张超、杨林伟、潘月鹏、程杰、王思柱，同时感谢项目导师和所有参与项目的贡献者。</p>
<div data-rmiz=""><div data-rmiz-content="not-found" style="visibility:visible"><img src="https://realfuture.ai/img/blog/2024-11-21/02.png" alt="02" style="cursor:pointer"></div></div>
<div data-rmiz=""><div data-rmiz-content="not-found" style="visibility:visible"><img src="https://realfuture.ai/img/blog/2024-11-21/03.png" alt="03" style="cursor:pointer"></div></div>
<h2 class="anchor anchorWithStickyNavbar_I2Xo" id="关于大赛">关于大赛<a href="https://realfuture.ai/blog/2024/11/21/#%E5%85%B3%E4%BA%8E%E5%A4%A7%E8%B5%9B" class="hash-link" aria-label="Direct link to 关于大赛" title="Direct link to 关于大赛">​</a></h2>
<p>“2024 中国互联网发展创新与投资大赛（开源）”在中央网信办信息化发展局的指导下，由中国互联网发展基金会、中国网络空间研究院、中国互联网投资基金联合主办。本届大赛以“开源创新，共建生态”为主题，围绕国家在开源人才培养和开源生态建设方面的重大战略需求，聚焦关键技术领域以及人工智能、物联网、云原生等前沿技术设置开源赛道，旨在为国内开源行业的企业、开发者和创业者提供展示、交流与合作的平台，激发开源创新活力，选拔优秀开源项目，培养开源实践人才，推动开源生态高质量发展。</p>
<p>本届大赛是继 2022 年中国开源创新大赛之后第二届连续举办，大赛邀请全国知名高校、科研机构、开源社区和企业界资深专家联合组成大赛组织委员会、评审委员会，保持大赛的权威性和中立性，更多详情请访问:</p>
<ul>
<li><a href="http://bs.bjos.club/" target="_blank" rel="noopener noreferrer">http://bs.bjos.club</a></li>
<li><a href="http://bjos.csdn.net/" target="_blank" rel="noopener noreferrer">http://bjos.csdn.net</a></li>
<li><a href="http://bjos.oschina.net/" target="_blank" rel="noopener noreferrer">http://bjos.oschina.net</a></li>
<li><a href="https://pages.segmentfault.com/kyds" target="_blank" rel="noopener noreferrer">https://pages.segmentfault.com/kyds</a></li>
</ul>
<h2 class="anchor anchorWithStickyNavbar_I2Xo" id="关于-streampark">关于 StreamPark<a href="https://realfuture.ai/blog/2024/11/21/#%E5%85%B3%E4%BA%8E-streampark" class="hash-link" aria-label="Direct link to 关于 StreamPark" title="Direct link to 关于 StreamPark">​</a></h2>
<p>StreamPark 是一个流处理应用开发与管理框架，旨在简化流处理应用的构建和管理。它为 Apache Flink 和 Apache Spark 提供开发框架与一站式管控平台，核心能力包括应用开发、调试、交互查询、部署和运维等。项目于 2021 年 4 月以 StreamX 为名开源，2022 年 8 月更名为 StreamPark，并于同年 9 月 1 日正式进入 Apache 软件基金会孵化器。文章发布时，项目已在天翼云、中国联通、长安汽车、杭州银行和自如等企业的生产环境中使用。</p>
<div data-rmiz=""><div data-rmiz-content="not-found" style="visibility:visible"><img src="https://realfuture.ai/img/blog/2024-11-21/04.png" alt="04" style="cursor:pointer"></div></div>
<h2 class="anchor anchorWithStickyNavbar_I2Xo" id="感谢认可-再接再励">感谢认可 再接再励<a href="https://realfuture.ai/blog/2024/11/21/#%E6%84%9F%E8%B0%A2%E8%AE%A4%E5%8F%AF-%E5%86%8D%E6%8E%A5%E5%86%8D%E5%8A%B1" class="hash-link" aria-label="Direct link to 感谢认可 再接再励" title="Direct link to 感谢认可 再接再励">​</a></h2>
<p>Apache StreamPark 作为一个年轻的开源项目，连续两次在具有如此权威性和中立性的国家单位指导举办的大赛中，经过角逐获得奖项，我们深感荣幸，不仅证明了项目的价值，更进一步提升了项目影响力和知名度，这个奖项是对长期以来相信开源，默默贡献开源的开发团队的嘉许和认可，同时也鞭策着我们更加努力的做好项目，建设发展好社区。后续我们将继续保持开发者谦逊朴素的本质，以做好一个项目为原则，秉承更加兼容并包的心态，迎接更多的机遇与挑战，推动中国开源的繁荣发展。</p>]]></content:encoded>
            <category>StreamPark</category>
        </item>
        <item>
            <title><![CDATA[Apache StreamPark™ 助力天眼查实时平台建设｜效率数倍提升]]></title>
            <link>https://realfuture.ai/blog/2024/06/09/</link>
            <guid>https://realfuture.ai/blog/2024/06/09/</guid>
            <pubDate>Sun, 09 Jun 2024 00:00:00 GMT</pubDate>
            <description><![CDATA[天眼查通过 Apache StreamPark 统一管理近千个 Flink 作业，降低运维成本并提升交付效率。]]></description>
            <content:encoded><![CDATA[<blockquote>
<p>本文主要介绍天眼查在实时计算业务近千个 Flink 作业运维时面临作业开发和管理上的挑战，通过引入 Apache StreamPark 来解决这些挑战，介绍了在引入 StreamPark 落地过程中遇到的一些问题以及如何解决这些问题并成功落地，最后极大地降低运维成本，显著地提升人效。</p>
<p>GitHub: <a href="https://github.com/apache/streampark" target="_blank" rel="noopener noreferrer">https://github.com/apache/streampark</a></p>
<p>欢迎关注、Star、Fork，参与贡献</p>
<p>供稿单位 | 北京天眼查</p>
<p>文章作者 | 李治霖</p>
<p>文章整理 | 杨林伟</p>
<p>内容校对 | 潘月鹏</p>
</blockquote>
<p>天眼查是中国领先的商业查询平台。自 2014 年创立以来，天眼查持续保持高速增长，行业渗透率超过 77%，月活跃用户数高达 3500 万，累计用户数 6 亿+，“天眼一下”已成为商业领域的超级符号，是首批获得央行备案企业征信资质的公司之一。经过公司多年深耕，平台共收录全国 3.4 亿、全球 6.4 亿社会实体，1000 多种商查信息维度实时更新，成为企业客户和个人用户商业查询的首选品牌。</p>
<div data-rmiz=""><div data-rmiz-content="not-found" style="visibility:visible"><img src="https://realfuture.ai/img/blog/2024-06-09/02.png" alt="02" style="cursor:pointer"></div></div>
<p>本文将介绍天眼查实时计算业务面临的挑战，如何通过 Apache StreamPark 平台来解决这些挑战，以及带来的显著效益和未来规划。</p>
<!-- -->
<h2 class="anchor anchorWithStickyNavbar_I2Xo" id="业务背景与挑战"><strong>业务背景与挑战</strong><a href="https://realfuture.ai/blog/2024/06/09/#%E4%B8%9A%E5%8A%A1%E8%83%8C%E6%99%AF%E4%B8%8E%E6%8C%91%E6%88%98" class="hash-link" aria-label="Direct link to 业务背景与挑战" title="Direct link to 业务背景与挑战">​</a></h2>
<p>天眼查有着庞大的用户基础和多样的业务维度，我们通过 Apache Flink® 这一强大的实时计算引擎，为用户提供更优质的产品和服务体验，我们的实时计算业务主要涵盖以下几个场景：</p>
<ul>
<li>
<p>实时数据 ETL 处理和数据传输。</p>
</li>
<li>
<p>C 端维度数据统计，包括用户行为、PV/UV 分析。</p>
</li>
<li>
<p>C 端业务数据与工商信息、风险信息、产权、股权、股东、案件等信息的实时关联分析。</p>
</li>
</ul>
<p>随着天眼查业务快速发展，实时作业已增至 800+ 个，未来很快会上千。面对如此规模的作业，我们在开发和管理上遇到了以下挑战：</p>
<ul>
<li>
<p><strong>作业运维困难</strong>：作业覆盖多个 Flink 版本，多版本 Flink 作业的运行和升级因 API 变动而成本高昂，且作业提交和参数调优依赖于复杂脚本，极大增加了维护难度和成本。</p>
</li>
<li>
<p><strong>作业开发低效</strong>：从本地 IDE 调试到测试环境部署，需经过编译、文件传输和命令执行等繁琐步骤，耗时且影响效率。</p>
</li>
<li>
<p><strong>缺乏自动重试机制</strong>：实时业务的多表关联操作易受网络和 IO 波动影响，导致 Flink 程序故障，需手动或额外程序介入恢复，增加了开发和维护成本。</p>
</li>
<li>
<p><strong>维护成本高昂</strong>：缺少集中化的日志、版本控制和配置管理工具，随着任务量上升，维护大量 JAR 包、提交脚本和 Flink 客户端配置变得日益复杂。</p>
</li>
</ul>
<div data-rmiz=""><div data-rmiz-content="not-found" style="visibility:visible"><img src="https://realfuture.ai/img/blog/2024-06-09/03.png" alt="03" style="cursor:pointer"></div></div>
<h2 class="anchor anchorWithStickyNavbar_I2Xo" id="streampark-落地实践"><strong>StreamPark 落地实践</strong><a href="https://realfuture.ai/blog/2024/06/09/#streampark-%E8%90%BD%E5%9C%B0%E5%AE%9E%E8%B7%B5" class="hash-link" aria-label="Direct link to streampark-落地实践" title="Direct link to streampark-落地实践">​</a></h2>
<p>为了解决上述问题，我司决定引入 StreamPark。我们在 StreamPark 项目刚开源的时候就开始关注，当时项目名还是 StreamX，此后也在一直密切关注着项目的发展，见证了其从开源到加入 Apache 软件基金会孵化的过程，其社区活跃度、用户口碑、发版次数等各项表现都很不错，有大量企业的真实使用案例，这增强了我们对 StreamPark 信心，因此引入 StreamPark 是自然而然的事情，我们尤其关注以下可以解决我们痛点的能力：</p>
<ul>
<li>
<p><strong>Git 式项目管理</strong>：为作业提供了便捷的版本控制和部署流程。</p>
</li>
<li>
<p><strong>强大的作业运维能力</strong>：显著提升了作业的管理和维护效率。</p>
</li>
<li>
<p><strong>精确的秒级告警系统</strong>：提供了实时监控和快速响应能力。</p>
</li>
<li>
<p><strong>一站式任务开发平台</strong>：为开发、测试和部署提供有力保障</p>
</li>
</ul>
<h3 class="anchor anchorWithStickyNavbar_I2Xo" id="git-式项目管理"><strong>Git 式项目管理</strong><a href="https://realfuture.ai/blog/2024/06/09/#git-%E5%BC%8F%E9%A1%B9%E7%9B%AE%E7%AE%A1%E7%90%86" class="hash-link" aria-label="Direct link to git-式项目管理" title="Direct link to git-式项目管理">​</a></h3>
<p>天眼查 90% 以上都是 JAR 作业，管理几百个JAR 作业是很头疼的问题，为了方便维护和管理先前我们通过 “开发人员名称-项目名称-模块-环境” 进行命名 JAR 文件名，这样带来了另一个问题，没办法直观区分要维护的作业在那个模块，如果非 owner 维护此作业得通过项目文档和代码来查看逻辑，需要找到项目代码与对应分支、作业的启动脚本等，这样大幅度增加开发人员工作量。</p>
<p>在 StreamPark 中我们惊喜地发现有项目管理功能，类似于 Git 集成，可以很好的解决了我们的痛点，我们通过简化的命名规范，实现了项目、人员、分支和环境的隔离。现在，我们能够瞬间定位到任意作业的代码和文档，极大提高了作业的可维护性和开发效率，显著提升了我们的运维效率。</p>
<div data-rmiz=""><div data-rmiz-content="not-found" style="visibility:visible"><img src="https://realfuture.ai/img/blog/2024-06-09/04.png" alt="04" style="cursor:pointer"></div></div>
<h3 class="anchor anchorWithStickyNavbar_I2Xo" id="秒级精确告警和自动运维"><strong>秒级精确告警和自动运维</strong><a href="https://realfuture.ai/blog/2024/06/09/#%E7%A7%92%E7%BA%A7%E7%B2%BE%E7%A1%AE%E5%91%8A%E8%AD%A6%E5%92%8C%E8%87%AA%E5%8A%A8%E8%BF%90%E7%BB%B4" class="hash-link" aria-label="Direct link to 秒级精确告警和自动运维" title="Direct link to 秒级精确告警和自动运维">​</a></h3>
<p>下面是我们的一个线上 Flink 作业。该作业在查询过程中访问第三方服务时发生 connection timeout 等错误（备注：Flink 重启策略设置为间隔重启三次，但最终仍然失败）。</p>
<div data-rmiz=""><div data-rmiz-content="not-found" style="visibility:visible"><img src="https://realfuture.ai/img/blog/2024-06-09/05.png" alt="05" style="cursor:pointer"></div></div>
<p>如上图，当收到任务告警时，我们开发同学在群里回复 1 的时候，我们发现<strong>作业已经成功被 StreamPark 拉起，只用不到 15 秒就完成了作业的重新提交和运行</strong>！</p>
<h3 class="anchor anchorWithStickyNavbar_I2Xo" id="平台用户权限管控"><strong>平台用户权限管控</strong><a href="https://realfuture.ai/blog/2024/06/09/#%E5%B9%B3%E5%8F%B0%E7%94%A8%E6%88%B7%E6%9D%83%E9%99%90%E7%AE%A1%E6%8E%A7" class="hash-link" aria-label="Direct link to 平台用户权限管控" title="Direct link to 平台用户权限管控">​</a></h3>
<p>StreamPark 提供了一套完善的权限管理机制，使得我们可以在 StreamPark 平台上对作业和用户进行精细的权限管理，有效避免了因用户权限过大而可能发生的误操作，减少了对作业运行稳定性和环境配置准确性的影响，对于企业级用户来说，这样的管理机制是非常必要的。</p>
<div data-rmiz=""><div data-rmiz-content="not-found" style="visibility:visible"><img src="https://realfuture.ai/img/blog/2024-06-09/06.png" alt="06" style="cursor:pointer"></div></div>
<h3 class="anchor anchorWithStickyNavbar_I2Xo" id="flink-sql-在线开发"><strong>Flink SQL 在线开发</strong><a href="https://realfuture.ai/blog/2024/06/09/#flink-sql-%E5%9C%A8%E7%BA%BF%E5%BC%80%E5%8F%91" class="hash-link" aria-label="Direct link to flink-sql-在线开发" title="Direct link to flink-sql-在线开发">​</a></h3>
<p>对于许多开发场景中需要提交 Flink SQL 作业的情况，现在我们可以完全摆脱在 IDEA 中编写代码的繁琐步骤。只需使用 StreamPark 平台，<strong>就能轻松实现  Flink SQL 作业的开发</strong>，以下是一个简单的案例。</p>
<div data-rmiz=""><div data-rmiz-content="not-found" style="visibility:visible"><img src="https://realfuture.ai/img/blog/2024-06-09/07.png" alt="07" style="cursor:pointer"></div></div>
<h3 class="anchor anchorWithStickyNavbar_I2Xo" id="完善的作业管理能力"><strong>完善的作业管理能力</strong><a href="https://realfuture.ai/blog/2024/06/09/#%E5%AE%8C%E5%96%84%E7%9A%84%E4%BD%9C%E4%B8%9A%E7%AE%A1%E7%90%86%E8%83%BD%E5%8A%9B" class="hash-link" aria-label="Direct link to 完善的作业管理能力" title="Direct link to 完善的作业管理能力">​</a></h3>
<p>StreamPark 还有更加完善的作业操作记录，对于一些提交时异常的作业，现可完全通过平台化查看失败日志，包括历史日志信息等。</p>
<div data-rmiz=""><div data-rmiz-content="not-found" style="visibility:visible"><img src="https://realfuture.ai/img/blog/2024-06-09/08.png" alt="08" style="cursor:pointer"></div></div>
<p>当然，StreamPark 还为我们提供了更加完善且友好的任务管理界面，可以直观地看到任务的运行情况。</p>
<div data-rmiz=""><div data-rmiz-content="not-found" style="visibility:visible"><img src="https://realfuture.ai/img/blog/2024-06-09/09.png" alt="09" style="cursor:pointer"></div></div>
<p>我们企业内部实时项目是高度抽象化代码开发的作业，每次开发新作业只需要修改一些外部传入的参数即可，通过 StreamPark 复制作业功能让我们告别了很多重复性工作，只需要在平台上复制已有作业，略微修改程序运行参数就可以提交一个新的作业！</p>
<div data-rmiz=""><div data-rmiz-content="not-found" style="visibility:visible"><img src="https://realfuture.ai/img/blog/2024-06-09/10.png" alt="10" style="cursor:pointer"></div></div>
<p>当然还有更多，这里就不一一列举了，StreamPark 在使用上足够的简单易用，分钟内即可上手使用，功能上足够的专注可靠，引入 StreamPark 以来解决了我们管理 Flink 作业面临的难题，带来了实实在在的方便，显著地提高了人效，给主创团队一个大大的赞！</p>
<h2 class="anchor anchorWithStickyNavbar_I2Xo" id="遇到的问题"><strong>遇到的问题</strong><a href="https://realfuture.ai/blog/2024/06/09/#%E9%81%87%E5%88%B0%E7%9A%84%E9%97%AE%E9%A2%98" class="hash-link" aria-label="Direct link to 遇到的问题" title="Direct link to 遇到的问题">​</a></h2>
<p>在 StreamPark 落地实践中，我们也遇到了一些问题，这里记录下来，期望给社区的用户带来一些输入和参考。</p>
<h3 class="anchor anchorWithStickyNavbar_I2Xo" id="华为云与开源-hadoop-存在兼容问题"><strong>华为云与开源 Hadoop 存在兼容问题</strong><a href="https://realfuture.ai/blog/2024/06/09/#%E5%8D%8E%E4%B8%BA%E4%BA%91%E4%B8%8E%E5%BC%80%E6%BA%90-hadoop-%E5%AD%98%E5%9C%A8%E5%85%BC%E5%AE%B9%E9%97%AE%E9%A2%98" class="hash-link" aria-label="Direct link to 华为云与开源-hadoop-存在兼容问题" title="Direct link to 华为云与开源-hadoop-存在兼容问题">​</a></h3>
<p>我们的作业均采用 Flink on YARN 模式并部署在华为云。在使用 StreamPark 部署作业的过程中，作业可以成功部署到华为 Hadoop 集群，但获取作业状态时，对 YARN ResourceManager 的请求被拒绝。我们及时与社区沟通、寻求解决方案，并记录了 issue：
<a href="https://github.com/apache/streampark/issues/3566" target="_blank" rel="noopener noreferrer">https://github.com/apache/streampark/issues/3566</a></p>
<p>最后在社区 PMC 成员华杰老师和华为云同学的协助下，成功解决了问题：由于云产品本身内部的安全认证机制导致 StreamPark 无法正常访问云 ResourceManager。</p>
<p>解决方案 (仅供参考 - 根据不同环境添加不同依赖)</p>
<p>将 STREAMPARK_HOME/lib 目录中 HADOOP 相关两个包删除：</p>
<div class="language-shell codeBlockContainer_eR_5 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_jz8P"><pre tabindex="0" class="prism-code language-shell codeBlock_tQzK thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_J4lo"><span class="token-line" style="color:#F8F8F2"><span class="token plain">hadoop-client-api-3.3.4.jar</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">hadoop-client-runtime-3.3.4.jar</span><br></span></code></pre><div class="buttonGroup_EiCC"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_azoe" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_HjTd"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_dSkr"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>替换以下华为云 HADOOP 依赖:</p>
<div class="language-shell codeBlockContainer_eR_5 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_jz8P"><pre tabindex="0" class="prism-code language-shell codeBlock_tQzK thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_J4lo"><span class="token-line" style="color:#F8F8F2"><span class="token plain">commons-configuration2-2.1.1.jar</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">commons-lang-2.6.0.wso2v1.jar</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">hadoop-auth-3.1.1-hw-ei-xxx.jar</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">hadoop-common-3.1.1-hw-ei-xxx.jar</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">hadoop-hdfs-client-3.1.1-hw-ei-xxx.jar</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">hadoop-plugins-8.1.2-xxx.jar</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">hadoop-yarn-api-3.1.1-hw-ei-xxx.jar</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">hadoop-yarn-client-3.1.1-hw-ei-xxx.jar</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">hadoop-yarn-common-3.1.1-hw-ei-xxx.jar</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">httpcore5-h2-5.1.5.jar</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">jaeger-core-1.6.0.jar</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">mysql-connector-java-8.0.28.jar</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">opentracing-api-0.33.0.jar</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">opentracing-noop-0.33.0.jar</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">opentracing-util-0.33.0.jar</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">protobuf-java-2.5.0.jar</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">re2j-1.7.jar</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">stax2-api-4.2.1.jar</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">woodstox-core-5.0.3.jar</span><br></span></code></pre><div class="buttonGroup_EiCC"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_azoe" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_HjTd"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_dSkr"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<h3 class="anchor anchorWithStickyNavbar_I2Xo" id="其他-bug"><strong>其他 BUG</strong><a href="https://realfuture.ai/blog/2024/06/09/#%E5%85%B6%E4%BB%96-bug" class="hash-link" aria-label="Direct link to 其他-bug" title="Direct link to 其他-bug">​</a></h3>
<p>在深入使用的过程中，我们也发现了一些问题。为了更好地改善与优化 StreamPark 的功能，我们提出了一些具体的建议和解决方案，例如：</p>
<ul>
<li>
<p><strong>依赖冲突</strong>：加载 Flink 依赖时出现冲突的解决（详见：Pull Request #3568）。</p>
</li>
<li>
<p><strong>服务稳定性</strong>：拦截用户程序 JVM 退出，防止 StreamPark 平台因用户程序异常退出（详见：Pull Request #3659）。</p>
</li>
<li>
<p><strong>资源优化</strong>：为减轻资源负担，限制 StremaPark 构建项目的并发数，通过配置参数来控制项目最大构建数量（详见：Pull Request #3696）。</p>
</li>
</ul>
<h2 class="anchor anchorWithStickyNavbar_I2Xo" id="带来的收益"><strong>带来的收益</strong><a href="https://realfuture.ai/blog/2024/06/09/#%E5%B8%A6%E6%9D%A5%E7%9A%84%E6%94%B6%E7%9B%8A" class="hash-link" aria-label="Direct link to 带来的收益" title="Direct link to 带来的收益">​</a></h2>
<p>Apache StreamPark 为我们带来了显著的收益，<strong>主要体现在其一站式服务能力，使得业务开发人员能够在一个统一的平台上完成 Flink 作业的开发、编译、提交和管理</strong>。极大地节省了我们在 Flink 作业开发和部署上的时间，显著地提升了开发效率，并实现了从用户权限管理到 Git 部署、任务提交、告警、自动恢复的全流程自动化，有效解决了 Apache Flink® 运维的复杂性。</p>
<div data-rmiz=""><div data-rmiz-content="not-found" style="visibility:visible"><img src="https://realfuture.ai/img/blog/2024-06-09/11.png" alt="11" style="cursor:pointer"></div></div>
<p>目前在天眼查平台，StreamPark 带来的具体成效包括：</p>
<ul>
<li>
<p>实时作业上线和测试部署流程简化了 <strong>70%</strong> 。</p>
</li>
<li>
<p>实时作业的运维成本降低了 <strong>80%</strong>，开发人员可以更专注于代码逻辑 。</p>
</li>
<li>
<p>告警时效性提高了 <strong>5倍</strong> 以上，从分钟级降低到秒级，实现了 <strong>5秒内</strong> 感知并处理任务异常。</p>
</li>
<li>
<p>对于任务失败，StreamPark 能够自动恢复，无需人工干预。</p>
</li>
<li>
<p>通过 GitLab 与 StreamPark 的集成，简化了编译项目和作业提交流程，大幅降低了开发和维护成本。</p>
</li>
</ul>
<h2 class="anchor anchorWithStickyNavbar_I2Xo" id="未来规划"><strong>未来规划</strong><a href="https://realfuture.ai/blog/2024/06/09/#%E6%9C%AA%E6%9D%A5%E8%A7%84%E5%88%92" class="hash-link" aria-label="Direct link to 未来规划" title="Direct link to 未来规划">​</a></h2>
<p>未来我们计划将内部自研实时计算平台上部署的 300+ Flink 作业和其他方式维护的 500+ Flink 作业全部迁移至 StreamPark 进行统一管理维护，后续遇到一些可优化或可增强功能点，我们会及时与社区开发人员沟通并回馈贡献社区，让 StreamPark 变得更易用、更好用。</p>
<p>在本文的最后，我们衷心感谢 Apache Streampark 社区，特别是 PMC 成员华杰老师，在我们使用 StreamPark 过程中持续地跟进，提供了宝贵的技术支持，我们深刻感受到 Apache StreamPark 社区认真的态度和热情。同时也非常感谢华为云同学在云部署上支持与问题排查。</p>
<p>我们期待未来与 StreamPark 社区继续合作，共同推动实时计算技术的发展，期望 StreamPark 在未来做得越来越好，成为新晋 Apache 项目的代表！</p>]]></content:encoded>
            <category>StreamPark</category>
            <category>Engineering</category>
        </item>
        <item>
            <title><![CDATA[自如基于 Apache StreamPark™ + Paimon 实现数据一键入湖最佳实践]]></title>
            <link>https://realfuture.ai/blog/2024/03/26/</link>
            <guid>https://realfuture.ai/blog/2024/03/26/</guid>
            <pubDate>Tue, 26 Mar 2024 00:00:00 GMT</pubDate>
            <description><![CDATA[自如基于 Apache StreamPark 与 Apache Paimon，完成 MySQL 数据入湖链路的架构升级。]]></description>
            <content:encoded><![CDATA[<blockquote>
<p>本文主要介绍了自如 MySQL 数据迁移至 Hive 的架构升级演进，原有架构涉及到的组件众多，链路复杂，遇到很多挑战，在使用 StreamPark + Paimon 这套组合方案后有效地解决了数据集成中遇到的困境和挑战，分享了 StreamPark + Paimon 在实际应用中具体的实践方案，以及这套新秀组合方案带来的优势和收益。</p>
<p>StreamPark: <a href="https://github.com/apache/streampark" target="_blank" rel="noopener noreferrer">https://github.com/apache/streampark</a></p>
<p>Paimon: <a href="https://github.com/apache/paimon" target="_blank" rel="noopener noreferrer">https://github.com/apache/paimon</a></p>
<p>欢迎关注、Star、Fork，参与贡献</p>
<p>供稿单位｜北京自如信息科技有限公司</p>
<p>文章作者｜刘涛、梁研生、魏林子</p>
<p>文章整理｜杨林伟</p>
<p>内容校对｜潘月鹏</p>
</blockquote>
<!-- -->
<h2 class="anchor anchorWithStickyNavbar_I2Xo" id="数据集成业务背景"><strong>数据集成业务背景</strong><a href="https://realfuture.ai/blog/2024/03/26/#%E6%95%B0%E6%8D%AE%E9%9B%86%E6%88%90%E4%B8%9A%E5%8A%A1%E8%83%8C%E6%99%AF" class="hash-link" aria-label="Direct link to 数据集成业务背景" title="Direct link to 数据集成业务背景">​</a></h2>
<p>自如租房业务的数据集成场景主要来源于各业务线的 MySQL 表同步到 Hive 表的需求。这一需求包含了每天同步的 MySQL 业务表数量超过 4400 个，以及超过 8000 多个的 Hive ETL 加工任务，每天新产生数据量有 50T，而且这些数字还在不断增长。根据数据的新鲜度需求分为低新鲜度（T+1 day）和高新鲜度（T+10 minutes）两种，每天同步调度 4000 多个低新鲜度数据表，以及每天同步调度 400 多个高新鲜度数据表，用以确保数据的及时性和准确性。</p>
<p>自如的数据集成方案根据业务使用场景主要可分为两种：</p>
<ul>
<li><strong>低新鲜度</strong>：低新鲜度对数据的时效性要求是 <strong>T+1day</strong>，每日定时凌晨 00:00 采用 Hive jdbc handler 进行 MySQL 数据的全量拉取至 Hive，其基本流程如下图所示：</li>
</ul>
<div data-rmiz=""><div data-rmiz-content="not-found" style="visibility:visible"><img src="https://realfuture.ai/img/blog/2024-03-26/02.png" alt="02" style="cursor:pointer"></div></div>
<ul>
<li><strong>高新鲜度</strong>：此场景中要求数据实效性是 <strong>T+10minutes</strong>，我们复用了低新鲜度场景的快照拉取方法来实现全量数据的获取，并且初始化至 MySQL，同步利用 Canal 解析日志收集到 Kafka，然后使用 Flink 读取 kafka 中的数据并写入到 HDFS，最后用 Airflow 进行调度以合并增量数据至 Hive，其基本逻辑如下所示：</li>
</ul>
<div data-rmiz=""><div data-rmiz-content="not-found" style="visibility:visible"><img src="https://realfuture.ai/img/blog/2024-03-26/03.png" alt="03" style="cursor:pointer"></div></div>
<p>然而，当前架构存在着多方面的挑战和压力。首先是运维成本高昂，其次是计算压力、存储压力和网络压力都非常大。另外，虽然系统运行时间从 0:00 到 1:00 期间资源利用不充分，但其他时间段却面临着资源不足的情况。对此自如决定更新数据集成架构以提高系统的效率和稳定性。</p>
<h2 class="anchor anchorWithStickyNavbar_I2Xo" id="遇到的挑战"><strong>遇到的挑战</strong><a href="https://realfuture.ai/blog/2024/03/26/#%E9%81%87%E5%88%B0%E7%9A%84%E6%8C%91%E6%88%98" class="hash-link" aria-label="Direct link to 遇到的挑战" title="Direct link to 遇到的挑战">​</a></h2>
<p>在上述的两种场景中，我们在数据集成过程中遇到了以下挑战：</p>
<ul>
<li>
<p><strong>网络带宽超负荷问题</strong>：由于拉取任务达到 <strong>4000+</strong>，过多的镜像全量数据拉取对数据库网络带宽产生了巨大压力。</p>
</li>
<li>
<p><strong>资源利用率低效</strong>：上游数据从 MySQL 同步到 ODS 层表后，下游的加工表才能启动，导致在 0:00 到 1:00 之间，Hadoop 集群的 CPU 和内存资源并未得到充分利用。</p>
</li>
<li>
<p><strong>维护成本高昂</strong>：当数据库表结构发生改变时，需要同步修改 Airflow 脚本。否则，会出现不完整的字段，引起线上数据异常问题。</p>
</li>
<li>
<p><strong>问题排查困难</strong>：数据链路较长，当出现数据异常时，问题排查成本较高，问题可能出现在 Canal、Kafka、Flink、Airflow 调度中的任何一个环节，导致问题恢复时间长。</p>
</li>
<li>
<p><strong>Flink 作业难以统一管理</strong>：Flink 本身没有提供很好的部署和开发能力，在 Flink 任务数量增多后，管理和维护的时间成本也随之上升。</p>
</li>
</ul>
<p>为了解决上述问题，我们经过一系列调研后，决定采用 “<strong>StreamPark+Paimon</strong>” 的策略，那么选择它们的原因是什么呢？我们可以先看看它们的特性。</p>
<h3 class="anchor anchorWithStickyNavbar_I2Xo" id="paimon-的核心特性"><strong>Paimon 的核心特性</strong><a href="https://realfuture.ai/blog/2024/03/26/#paimon-%E7%9A%84%E6%A0%B8%E5%BF%83%E7%89%B9%E6%80%A7" class="hash-link" aria-label="Direct link to paimon-的核心特性" title="Direct link to paimon-的核心特性">​</a></h3>
<p><strong>在经过对 Apache Hudi / Iceberg / Paimon 几个数据湖框架的调研和综合评估之后，我们决定使用 Apache Paimon</strong>，Apache Paimon 是一项流式数据湖存储技术，可以为用户提供高吞吐低延时的数据摄入，流式订阅和实时查询能力，支持使用 Flink 和 Spark 构建实时 Lakehouse 架构，支持批/流数据处理操作，创新性地将 Lake 格式与 LSM 结构相结合，将实时流式更新引入 Lake 架构中，具有以下优点：</p>
<ul>
<li>
<p><strong>统一的批处理和流处理</strong>：Paimon 支持批量写入、批量读取和流式操作，提供了灵活的数据处理方式。</p>
</li>
<li>
<p><strong>数据湖功能</strong>：作为数据湖存储系统，Paimon 具有低成本、高可靠性和可扩展的元数据等特性。</p>
</li>
<li>
<p><strong>丰富的合并引擎</strong>：Paimon 提供了多种合并引擎，可以根据需求选择保留最新数据、进行局部更新或进行聚合操作。</p>
</li>
<li>
<p><strong>自动生成变更日志</strong>：Paimon 支持多种 Changelog 生产者，能够自动生成正确完整的变更日志，简化流式任务分析。</p>
</li>
<li>
<p><strong>丰富的表类型</strong>：Paimon 支持主键表和仅追加表，以及多种表类型，如内部表、外部表、分区表和临时表。</p>
</li>
<li>
<p><strong>支持表结构变更同步</strong>：当数据源表结构发生变化时，Paimon 能自动识别并同步这些变化。</p>
</li>
</ul>
<p>Paimon 可以结合 Apache Spark™ 来使用，我们场景是 Paimon 结合 Flink 的方式，这样一来 “<strong>如何管理 4000+个 Flink 数据同步作业</strong>” 将会是我们面临的新问题。在全面调研了相关项目，经过各项维度综合评估后，<strong>我们决定采用 StreamPark</strong>，那么为什么选择 StremaPark 呢？</p>
<h3 class="anchor anchorWithStickyNavbar_I2Xo" id="streampark-的核心特性"><strong>StreamPark 的核心特性</strong><a href="https://realfuture.ai/blog/2024/03/26/#streampark-%E7%9A%84%E6%A0%B8%E5%BF%83%E7%89%B9%E6%80%A7" class="hash-link" aria-label="Direct link to streampark-的核心特性" title="Direct link to streampark-的核心特性">​</a></h3>
<p>Apache StreamPark 是一个流处理开发管理框架，提供了一套快捷的 API 用来开发 Flink/Spark 作业，此外还提供了一个一站式的流处理作业开发管理平台，从流处理作业开发到上线全生命周期都做了支持，StreamPark 主要包含下面这些核心特点：</p>
<ul>
<li>
<p><strong>流处理应用开发框架</strong>：基于 StreamPark，开发者可以轻松构建和管理流处理应用程序，更好地利用  Apache Flink® 去编写流处理应用程序。</p>
</li>
<li>
<p><strong>完善的作为管理能力</strong>：StreamPark 提供一站式流任务开发管理平台，支持了 Flink / Spark 从应用开发到调试、部署、运维等全生命周期的能力支持，让 Flink / Spark 作业变得简单。</p>
</li>
<li>
<p><strong>完成度高</strong>：StreamPark 支持了 Flink 多版本，可以做到一个平台灵活切换，同时支持 Flink 所的部署模式，有效解决了 Flink on YARN / K8s 部署过于繁琐的问题，通过自动化流程，简化了任务的构建、测试和部署流程，并提高了开发效率。</p>
</li>
<li>
<p><strong>丰富的管理 API</strong>：StreamPark 提供了作业操作的 API，包括作业创建、拷贝、构建、部署、基于 checkpoint/savepoint 的停止和启动等功能，使外部系统调用 Apache Flink® 任务变得易于实现。</p>
</li>
</ul>
<h2 class="anchor anchorWithStickyNavbar_I2Xo" id="streampark--paimon-实践"><strong>StreamPark + Paimon 实践</strong><a href="https://realfuture.ai/blog/2024/03/26/#streampark--paimon-%E5%AE%9E%E8%B7%B5" class="hash-link" aria-label="Direct link to streampark--paimon-实践" title="Direct link to streampark--paimon-实践">​</a></h2>
<p>接下来，我们将继续分享自如是如何基于 <strong>StreamPark + Paimon</strong> 进行架构优化改造的，我们先看架构升级前后的对比。</p>
<h3 class="anchor anchorWithStickyNavbar_I2Xo" id="架构升级前"><strong>架构升级前</strong><a href="https://realfuture.ai/blog/2024/03/26/#%E6%9E%B6%E6%9E%84%E5%8D%87%E7%BA%A7%E5%89%8D" class="hash-link" aria-label="Direct link to 架构升级前" title="Direct link to 架构升级前">​</a></h3>
<p>数据集成模块在改造之前的系统交互流程如下：</p>
<div data-rmiz=""><div data-rmiz-content="not-found" style="visibility:visible"><img src="https://realfuture.ai/img/blog/2024-03-26/04.png" alt="04" style="cursor:pointer"></div></div>
<p><strong>Step1</strong>（用户发起接入申请）：首先用户在数据接入平台选择一个表，然后点击申请接入按钮：</p>
<div data-rmiz=""><div data-rmiz-content="not-found" style="visibility:visible"><img src="https://realfuture.ai/img/blog/2024-03-26/05.png" alt="05" style="cursor:pointer"></div></div>
<p><strong>Step2</strong>（发起OA系统审批流程）：OA 系统接收到接入申请，会发起工作流审批，如审批失败会驳回申请，审批通过才会继续下一步。</p>
<p><strong>Step3</strong>（数据接入平台处理审批通过事件）：数据接入平台调用 Canal 接口部署 Canal 任务，将表中的 Binlog 数据传入 Kafka ：</p>
<div data-rmiz=""><div data-rmiz-content="not-found" style="visibility:visible"><img src="https://realfuture.ai/img/blog/2024-03-26/06.png" alt="06" style="cursor:pointer"></div></div>
<p><strong>Step4</strong>（Flink 任务部署）：人工使用 Flink Session Submit UI 部署 Flink 模板作业，负责解析 Kafka 中的 Binlog 变化数据，并将数据写入 HDFS，同时映射成 Hive 外部增量表：</p>
<div data-rmiz=""><div data-rmiz-content="not-found" style="visibility:visible"><img src="https://realfuture.ai/img/blog/2024-03-26/07.png" alt="07" style="cursor:pointer"></div></div>
<p><strong>Step5</strong>（Airflow调度初始化表）：创建 Hive 映射增量表和全量表并用 Airflow 调度完成首次初始化:</p>
<div data-rmiz=""><div data-rmiz-content="not-found" style="visibility:visible"><img src="https://realfuture.ai/img/blog/2024-03-26/08.png" alt="08" style="cursor:pointer"></div></div>
<p><strong>Step6</strong>（数据合并到 Hive 全量表）：配置调度通过 Hive Merge 方式将 Hive 外部增量表的数据合并到 Hive 全量表中</p>
<div data-rmiz=""><div data-rmiz-content="not-found" style="visibility:visible"><img src="https://realfuture.ai/img/blog/2024-03-26/09.png" alt="09" style="cursor:pointer"></div></div>
<h3 class="anchor anchorWithStickyNavbar_I2Xo" id="架构升级后"><strong>架构升级后</strong><a href="https://realfuture.ai/blog/2024/03/26/#%E6%9E%B6%E6%9E%84%E5%8D%87%E7%BA%A7%E5%90%8E" class="hash-link" aria-label="Direct link to 架构升级后" title="Direct link to 架构升级后">​</a></h3>
<p>改造后的系统交互流程图如下：</p>
<div data-rmiz=""><div data-rmiz-content="not-found" style="visibility:visible"><img src="https://realfuture.ai/img/blog/2024-03-26/10.png" alt="10" style="cursor:pointer"></div></div>
<p>对比改造前和改造后的交互流程图，可以看出前两个步骤的流程（表接入申请与审批）是一样的，只是审批通过之后的事件<strong>监听处理方式</strong>的差异。</p>
<ul>
<li>
<p><strong>改造前</strong>：调用 Canal 接口去部署 Canal 任务（旧的逻辑）；</p>
</li>
<li>
<p><strong>改造后</strong>：调用 StreamPark 的 API 接口完成 Flink Paimon 的任务部署。</p>
</li>
</ul>
<p>接下来看看使用 Paimon 来完成数据的集成的。</p>
<h3 class="anchor anchorWithStickyNavbar_I2Xo" id="paimon-实现一键入-hive"><strong>Paimon 实现一键入 Hive</strong><a href="https://realfuture.ai/blog/2024/03/26/#paimon-%E5%AE%9E%E7%8E%B0%E4%B8%80%E9%94%AE%E5%85%A5-hive" class="hash-link" aria-label="Direct link to paimon-实现一键入-hive" title="Direct link to paimon-实现一键入-hive">​</a></h3>
<p>在 Apache Paimon 0.5 版本后，提供了 CDC 数据集成能力，通过官方提供的 paimon-action jar 可以很方便的将 MySQL、Kafka、Mongo 等中的数据实时摄入到 Paimon 中，我们正在使用的是 paimon-flink-action ，采用了 <strong>mysql-sync-database（整库同步）</strong>，并通过“<strong>—including_tables</strong>” 参数选择要同步的表。这种同步模式有效地节省了大量资源开销，相比每个表启动一个 Flink 任务而言，避免了资源的大量浪费。</p>
<p>paimon-flink-action 提供了自动创建 Paimon 表的功能，并支持 Schema Evolution（例如，当 MySQL 表字段发生变化时，Paimon 表会相应变化，无需额外操作）。整个操作流程高效而顺畅，解决了原始架构因添加字段而产生的不必要运维成本，paimon-action 具体使用如下，更多请参考Paimon 官网文档。</p>
<div class="language-shell codeBlockContainer_eR_5 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_jz8P"><pre tabindex="0" class="prism-code language-shell codeBlock_tQzK thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_J4lo"><span class="token-line" style="color:#F8F8F2"><span class="token plain">&lt;FLINK_HOME&gt;/bin/flink run \</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    /path/to/paimon-flink-action-0.8-SNAPSHOT.jar \</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    mysql_sync_table</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    --warehouse &lt;warehouse-path&gt; \</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    --database &lt;database-name&gt; \</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    --table &lt;table-name&gt; \</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    [--partition_keys &lt;partition_keys&gt;] \</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    [--primary_keys &lt;primary-keys&gt;] \</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    [--type_mapping &lt;option1,option2...&gt;] \</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    [--computed_column &lt;'column-name=expr-name(args[, ...])'&gt; [--computed_column ...]] \</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    [--metadata_column &lt;metadata-column&gt;] \</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    [--mysql_conf &lt;mysql-cdc-source-conf&gt; [--mysql_conf &lt;mysql-cdc-source-conf&gt; ...]] \</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    [--catalog_conf &lt;paimon-catalog-conf&gt; [--catalog_conf &lt;paimon-catalog-conf&gt; ...]] \</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    [--table_conf &lt;paimon-table-sink-conf&gt; [--table_conf &lt;paimon-table-sink-conf&gt; ...]]</span><br></span></code></pre><div class="buttonGroup_EiCC"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_azoe" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_HjTd"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_dSkr"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>引入 Paimon 后缩短了整个数据接入链路，消除了对 Canal、Kafka、Airflow 的依赖，使得 MySQL 直接以分钟级速度与 Hive 对接，整体环境清爽高效。此外，Paimon 完全兼容 Hive 端数据读取，转换成本极低，对原始架构脚本的使用也具备良好的兼容性，Paimon 还支持 Tag 功能，可以视为轻量级的快照，大幅降低了存储成本。</p>
<h3 class="anchor anchorWithStickyNavbar_I2Xo" id="streampark--paimon-落地实践"><strong>StreamPark + Paimon 落地实践</strong><a href="https://realfuture.ai/blog/2024/03/26/#streampark--paimon-%E8%90%BD%E5%9C%B0%E5%AE%9E%E8%B7%B5" class="hash-link" aria-label="Direct link to streampark--paimon-落地实践" title="Direct link to streampark--paimon-落地实践">​</a></h3>
<p>StreamPark 在 2.1.2 版本中更好的支持了 JAR 类型的作业，使得 Paimon 类型的数据集成作业更简单了，下面的示例，演示了如何使用 StreamPark 快速开发 Paimon 数据迁移类型的作业：</p>
<p>诚然 StreamPark 在 2.1.2 版本之后已经特别针对 Paimon 数据集成类作业做了支持，但是这种手动创建作业，输入作业参数的方式还是不满足我们的实际需求，我们需要更灵活的作业创建，可以通过调用 API 的方式快速完成作业创建、启动... 经过我们的调研发现 StreamPark 已经完整的开放了作业的各项操作 API，如作业的复制、创建、部署、启动、停止等，这样一来，我们通过定时调度就可以非常方便和 StreamPark 组合，来快速完成作业的开发和运行，具体方式如下：</p>
<p><strong>Step1</strong>：首先，会调用api copy 模版接口，并传入参数，相关截图如下：</p>
<div data-rmiz=""><div data-rmiz-content="not-found" style="visibility:visible"><img src="https://realfuture.ai/img/blog/2024-03-26/11.png" alt="11" style="cursor:pointer"></div></div>
<p>这样该作业就快速创建完成，参数会通过 copy 接口传入，具体参数如下：</p>
<div data-rmiz=""><div data-rmiz-content="not-found" style="visibility:visible"><img src="https://realfuture.ai/img/blog/2024-03-26/12.png" alt="12" style="cursor:pointer"></div></div>
<p><strong>Step2</strong>：接着，调用api构建作业镜像：</p>
<div data-rmiz=""><div data-rmiz-content="not-found" style="visibility:visible"><img src="https://realfuture.ai/img/blog/2024-03-26/13.png" alt="13" style="cursor:pointer"></div></div>
<p><strong>Step3</strong>：继续调用api启动作业：</p>
<div data-rmiz=""><div data-rmiz-content="not-found" style="visibility:visible"><img src="https://realfuture.ai/img/blog/2024-03-26/14.png" alt="14" style="cursor:pointer"></div></div>
<p>最后，任务启动成功后，可以在 StreamPark 平台看到任务的相关状态信息以及整体任务的资源概况：</p>
<div data-rmiz=""><div data-rmiz-content="not-found" style="visibility:visible"><img src="https://realfuture.ai/img/blog/2024-03-26/15.png" alt="15" style="cursor:pointer"></div></div>
<p>并可以点击Application Name 调度Flink Web UI：</p>
<div data-rmiz=""><div data-rmiz-content="not-found" style="visibility:visible"><img src="https://realfuture.ai/img/blog/2024-03-26/16.png" alt="16" style="cursor:pointer"></div></div>
<p>最后可以直接在 Hive 端查询 Paimon 表，获取所需的数据，其中 Paimon 表是经过 Flink 处理的、延时较低的数据同步目标表。Hue 中 Hive 查询 Paimon 表截图如下</p>
<div data-rmiz=""><div data-rmiz-content="not-found" style="visibility:visible"><img src="https://realfuture.ai/img/blog/2024-03-26/17.png" alt="17" style="cursor:pointer"></div></div>
<p>通过以上步骤，业务方可以方便地发起接入申请，经过审批流程后，通过 StreamPark 创建部署 Flink 作业，数据通过 Flink 作业入 Paimon 表，使用户能够轻松地在 Hive 端进行查询操作，整个流程简化了用户操作，提高了数据接入的效率和可维护性。</p>
<h2 class="anchor anchorWithStickyNavbar_I2Xo" id="带来的收益"><strong>带来的收益</strong><a href="https://realfuture.ai/blog/2024/03/26/#%E5%B8%A6%E6%9D%A5%E7%9A%84%E6%94%B6%E7%9B%8A" class="hash-link" aria-label="Direct link to 带来的收益" title="Direct link to 带来的收益">​</a></h2>
<p>自如通过使用 Paimon 和 StreamPark ，带来了如下优势和效益：</p>
<ul>
<li>
<p><strong>网络资源和数据库压力优化</strong>：通过直接从 Paimon 表获取数据快照，解决了凌晨从业务数据库拉取数据导致的网络资源紧张和数据库压力过大问题，同时降低了数据存储成本。</p>
</li>
<li>
<p><strong>作业管理接口提升效率</strong>：使用 StreamPark 的作业管理接口轻松解决了手动部署 Flink 任务的问题，消除了人员依赖时间导致任务不及时部署的情况，提高了效率，同时减少了沟通成本，提升了 Flink 作业的管理效率。</p>
</li>
<li>
<p><strong>降低开发、维护成本</strong>：解决了之前方案链路长导致的维护成本高和问题定位慢的问题，同时解决了字段变化导致的字段不一致问题，实现了数据接入的流批统一，降低了开发和维护的成本。</p>
</li>
<li>
<p><strong>降低了数据集成调度资源和计算资源的使用成本</strong>：不再依赖外部调度系统进行增量数据的合并，减少了调度资源的使用。也不再依赖 Hive 资源进行合并操作，降低了合并增量数据对 Hive 计算资源的花销成本。</p>
</li>
</ul>
<h2 class="anchor anchorWithStickyNavbar_I2Xo" id="结语与期望"><strong>结语与期望</strong><a href="https://realfuture.ai/blog/2024/03/26/#%E7%BB%93%E8%AF%AD%E4%B8%8E%E6%9C%9F%E6%9C%9B" class="hash-link" aria-label="Direct link to 结语与期望" title="Direct link to 结语与期望">​</a></h2>
<p>我们衷心地感谢 <strong>Apache StreamPark</strong> 社区在我们使用 StreamPark API 时提供的无私帮助。他们专业的服务精神和以用户为本的态度，使我们得以更加高效、流畅地运用这一强大框架。作为一套卓越的框架，StreamPark 不但拥有出色的功能，而且能支持一系列如任务复制、创建、部署、启动、停止以及状态监控的操作，并在简化 Flink 任务的管理与维护方面显著地发挥了其价值。</p>
<p>同时，对 <strong>Apache Paimon</strong> 社区在自如 MySQL 入 Paimon 测试阶段给予我们的耐心与专业指导表示感谢，这是我们能够顺利完成测试的重要支持。Paimon 作为一项富有潜力的项目，无论是在功能实现还是团队协作方面，都展现了非凡的素质。</p>
<p>最后，我们对 Apache StreamPark 和 Apache Paimon 的未来之路满怀期待和信心，坚信它们能在未来会成为 Apache 的优秀项目。它们卓越的功能和和睦的社区合作模式，都为其在开源社区的成熟之路打下了坚实的基础。我们期待 StreamPark 和 Paimon 社区能一如既往地保持专业态度和良好的团队协作精神，不断推进项目发展，成为近年来新晋 Apache 项目的典范，以便对更广大的开发者社区产生更大的影响。</p>]]></content:encoded>
            <category>StreamPark</category>
            <category>Engineering</category>
        </item>
        <item>
            <title><![CDATA[长安汽车从自研平台到 Apache StreamPark™ 的升级实践]]></title>
            <link>https://realfuture.ai/blog/2024/03/05/</link>
            <guid>https://realfuture.ai/blog/2024/03/05/</guid>
            <pubDate>Tue, 05 Mar 2024 00:00:00 GMT</pubDate>
            <description><![CDATA[长安汽车引入 Apache StreamPark，统一 Flink 作业开发、部署与运维流程，降低平台维护成本并提升交付效率。]]></description>
            <content:encoded><![CDATA[<blockquote>
<p>长安汽车是中国汽车四大集群阵营企业之一，随着业务发展和数智化的推进，对数据的实效性要求越来越高，Flink 作业越来越多，长安汽车原本开发了一套流应用平台，用来满足开发人员对于 Flink 作业管理和运维工作的基础需求，但是在实际使用中面临诸多挑战和困境，最终使用 Apache StreamPark 来作为一站式实时计算平台，有效解决了之前面临的诸多困境，StreamPark 提供的解决方案简化了整个开发流程，在 Flink 作业开发部署上节省了很多时间，走出了作业运维管理的泥沼，显著地提升了效率。</p>
<p>供稿单位｜长安智能化研究院云平台开发所</p>
<p>编辑校对｜潘月鹏</p>
</blockquote>
<p>重庆长安汽车股份有限公司（简称“长安汽车”）成立于 1996 年 10 月 31 日，是中国汽车四大集团阵营企业，拥有 161 年历史底蕴，现在旗下包括长安启源、深蓝汽车、阿维塔、长安引力、长安凯程等自主品牌以及长安福特、长安马自达等合资品牌。</p>
<p>近些年随着汽车销量的不断增加与智能化程度的不断提升，车辆每天将产生千亿级别的 CAN 数据，清洗处理后的数据也在 50 亿级别，面对如此庞大且持续膨胀的数据规模，如何从海量数据中快速提取挖掘有价值的信息，为研发、生产、销售等部门提供数据支持，成为当前亟需解决的问题。</p>
<!-- -->
<h2 class="anchor anchorWithStickyNavbar_I2Xo" id="实时计算面临的挑战"><strong>实时计算面临的挑战</strong><a href="https://realfuture.ai/blog/2024/03/05/#%E5%AE%9E%E6%97%B6%E8%AE%A1%E7%AE%97%E9%9D%A2%E4%B8%B4%E7%9A%84%E6%8C%91%E6%88%98" class="hash-link" aria-label="Direct link to 实时计算面临的挑战" title="Direct link to 实时计算面临的挑战">​</a></h2>
<p>长安汽车数据的存储与分析处理主要由云上和云下两部分构成，云上指的是我们部署在腾讯云服务器上的大数据集群，使用 CDH 搭建，用于存储热数据；云下是部署在本地机房的 CDP 集群，从云上拉取同步数据，进行存储和分析。<strong>Flink 在长安汽车实时计算中一直扮演着重要角色，长安汽车开发了一套流应用平台，用来满足开发人员对 Flink 作业管理和运维工作的基础需求</strong>。但是在实际使用中，流应用平台存在以下四个方面的问题：</p>
<p>①<strong>功能单一</strong>: 只提供部署功能，无用户权限管理、团队管理、角色管理、项目管理，无法满足项目、团队管理需求。</p>
<p>②<strong>易用性不足</strong>: SQL 编写无提示、日志浏览不便、不支持调试、无错误检测、无版本管理、无配置中心等。</p>
<p>③<strong>可扩展性较差</strong>: 不支持在线扩容 Flink 集群、新增或更换 Flink 版本，新增 Flink Connectors、CDC 等。</p>
<p>④<strong>可维护性较差</strong>: 无日志查看、无版本管理、无配置中心等。</p>
<h2 class="anchor anchorWithStickyNavbar_I2Xo" id="为什么用-streampark"><strong>为什么用 StreamPark</strong><a href="https://realfuture.ai/blog/2024/03/05/#%E4%B8%BA%E4%BB%80%E4%B9%88%E7%94%A8-streampark" class="hash-link" aria-label="Direct link to 为什么用-streampark" title="Direct link to 为什么用-streampark">​</a></h2>
<p>针对 Flink 作业面临的困境，我们决定先从开源领域寻求解决方案，因此全面调研了 Apache StreamPark、Dxxky、strxxing-xx-web 等开源项目。<strong>我们从核心能力、稳定性、易用性、可扩展性、可维护性和操作体验等多个维度进行了评估，并结合当前的流作业开发需求与大数据平台规划，发现 Apache StreamPark 最符合我们的实际需求。因此，我们采用 StreamPark 作为流计算平台。</strong> StreamPark 具有以下优势：</p>
<h3 class="anchor anchorWithStickyNavbar_I2Xo" id="完善的基础管理能力"><strong>完善的基础管理能力</strong><a href="https://realfuture.ai/blog/2024/03/05/#%E5%AE%8C%E5%96%84%E7%9A%84%E5%9F%BA%E7%A1%80%E7%AE%A1%E7%90%86%E8%83%BD%E5%8A%9B" class="hash-link" aria-label="Direct link to 完善的基础管理能力" title="Direct link to 完善的基础管理能力">​</a></h3>
<p>StreamPark 解决了我们已有的流应用平台无用户权限管理、团队管理、角色管理、项目管理、团队管理等问题。</p>
<p>① StreamPark 平台提供了用户权限管理功能。这些功能可以确保用户只能访问其所需的数据和资源，并限制其对系统或作业的修改权限。对于企业级用户而言，这种管理功能非常必要，因为它有助于保护企业的数据安全、维护系统稳定性，并确保作业的顺利运行。通过合理地设置和管理用户权限，企业可以更好地控制数据访问和操作，从而降低风险并提高工作效率。</p>
<div data-rmiz=""><div data-rmiz-content="not-found" style="visibility:visible"><img src="https://realfuture.ai/img/blog/2024-03-05/02.png" alt="02" style="cursor:pointer"></div></div>
<h3 class="anchor anchorWithStickyNavbar_I2Xo" id="一站式流处理平台"><strong>一站式流处理平台</strong><a href="https://realfuture.ai/blog/2024/03/05/#%E4%B8%80%E7%AB%99%E5%BC%8F%E6%B5%81%E5%A4%84%E7%90%86%E5%B9%B3%E5%8F%B0" class="hash-link" aria-label="Direct link to 一站式流处理平台" title="Direct link to 一站式流处理平台">​</a></h3>
<p>StreamPark 解决了流应用平台易用性不足，SQL 编写无提示、日志浏览不方便、无错误检测、无版本管理、无配置中心等问题。</p>
<p>① StreamPark 具备完善的 SQL 校验功能，实现了自动 build/push 镜像，使用自定义类加载器，<strong>通过 Child-first 加载方式解决了 YARN 和 K8s 两种运行模式、支持了自由切换 Flink 版本等特性。</strong></p>
<p>② StreamPark 提供了作业监控和日志管理的功能，<strong>可以帮助用户实时监控作业的运行状态，查看作业的日志信息，以及进行故障排除</strong>。使得用户可以快速发现和解决作业运行中的问题。</p>
<h3 class="anchor anchorWithStickyNavbar_I2Xo" id="可扩展性强"><strong>可扩展性强</strong><a href="https://realfuture.ai/blog/2024/03/05/#%E5%8F%AF%E6%89%A9%E5%B1%95%E6%80%A7%E5%BC%BA" class="hash-link" aria-label="Direct link to 可扩展性强" title="Direct link to 可扩展性强">​</a></h3>
<p>StreamPark 解决了流应用平台可扩展性差、不支持在线扩容 Flink 集群、不支持新增或更换 Flink 版本、Flink Connector 不足等问题。</p>
<p>① StreamPark 具有良好的可扩展性和灵活性，<strong>支持大规模 Flink on YARN 作业运行，并能与现有 YARN 集群无缝集成</strong>，也可以根据需要进行定制和扩展。此外，StreamPark 还提供多种配置选项和功能扩展点，以满足用户的多样化需求。</p>
<p>② <strong>StreamPark 具备 Flink 作业开发所需的整套工具</strong>。在 StreamPark 中，对于编写代码的 Flink 作业，它提供了一种更优秀的解决方案，将程序配置进行了标准化，简化了编程模型，同时还提供了一系列连接器，显著降低了 DataStream 开发的难度。</p>
<div data-rmiz=""><div data-rmiz-content="not-found" style="visibility:visible"><img src="https://realfuture.ai/img/blog/2024-03-05/03.png" alt="03" style="cursor:pointer"></div></div>
<p>除了上述优点外，<strong>StreamPark 还能管理作业的完整生命周期，包括开发、部署、运行和问题诊断等环节，使开发人员能够专注于业务本身，无需过多关注 Flink 作业的管理与运维问题</strong>。StreamPark 的作业开发管理模块大致可分为三个部分：作业管理基础功能、JAR 作业管理和 Flink SQL 作业管理。</p>
<div data-rmiz=""><div data-rmiz-content="not-found" style="visibility:visible"><img src="https://realfuture.ai/img/blog/2024-03-05/04.png" alt="04" style="cursor:pointer"></div></div>
<h2 class="anchor anchorWithStickyNavbar_I2Xo" id="streampark落地实践"><strong>StreamPark落地实践</strong><a href="https://realfuture.ai/blog/2024/03/05/#streampark%E8%90%BD%E5%9C%B0%E5%AE%9E%E8%B7%B5" class="hash-link" aria-label="Direct link to streampark落地实践" title="Direct link to streampark落地实践">​</a></h2>
<p>为了使 StreamPark 在日常生产实践中与我们的需求更加契合，我们对其进行了一定的适应性改造：</p>
<h3 class="anchor anchorWithStickyNavbar_I2Xo" id="适应性改造"><strong>适应性改造</strong><a href="https://realfuture.ai/blog/2024/03/05/#%E9%80%82%E5%BA%94%E6%80%A7%E6%94%B9%E9%80%A0" class="hash-link" aria-label="Direct link to 适应性改造" title="Direct link to 适应性改造">​</a></h3>
<h4 class="anchor anchorWithStickyNavbar_I2Xo" id="告警信息改造"><strong>告警信息改造</strong><a href="https://realfuture.ai/blog/2024/03/05/#%E5%91%8A%E8%AD%A6%E4%BF%A1%E6%81%AF%E6%94%B9%E9%80%A0" class="hash-link" aria-label="Direct link to 告警信息改造" title="Direct link to 告警信息改造">​</a></h4>
<p>长安汽车针对 StreamPark 的一些特性进行了适应性改造，比如针对 StreamPark 的告警不仅支持邮件、飞书、钉钉和企业微信推送，还支持将告警信息按照重要程度进行分类，推送到不同的告警群与相关个人，方便相关运维人员及时捕捉重要告警信息，快速响应。</p>
<div data-rmiz=""><div data-rmiz-content="not-found" style="visibility:visible"><img src="https://realfuture.ai/img/blog/2024-03-05/05.png" alt="05" style="cursor:pointer"></div></div>
<h4 class="anchor anchorWithStickyNavbar_I2Xo" id="nocos-配置管理支持"><strong>Nocos 配置管理支持</strong><a href="https://realfuture.ai/blog/2024/03/05/#nocos-%E9%85%8D%E7%BD%AE%E7%AE%A1%E7%90%86%E6%94%AF%E6%8C%81" class="hash-link" aria-label="Direct link to nocos-配置管理支持" title="Direct link to nocos-配置管理支持">​</a></h4>
<p>为解决 Flink 应用的配置信息写死在 Jar 包中，给开发、测试、运维带来的不便，我们将 Nacos 与 StreamPark 平台进行集成，带来了如下优势：</p>
<p>① 配置集中管理，通过 StreamPark，开发人员可以集中管理所有 Flink 应用配置信息，实现配置的集中管理和更新，避免了在多个平台间进行切换和重复操作。同时加强了配置管理的安全性，对访问和修改配置的操作进行权限控制，防止未经授权的访问和修改。</p>
<p>② 配置动态更新，StreamPark 与 Nacos 的集成使得 Flink 应用能够及时获取最新的配置信息，实现配置的动态更新，避免了修改 Flink 配置信息后需要重新编译、发布、重启等繁琐流程，提高了系统的灵活性和响应速度。同时，StreamPark 可以利用 Nacos 的配置推送功能，实现配置信息的自动化更新。</p>
<div data-rmiz=""><div data-rmiz-content="not-found" style="visibility:visible"><img src="https://realfuture.ai/img/blog/2024-03-05/06.png" alt="06" style="cursor:pointer"></div></div>
<h3 class="anchor anchorWithStickyNavbar_I2Xo" id="遇到的问题及解决方案"><strong>遇到的问题及解决方案</strong><a href="https://realfuture.ai/blog/2024/03/05/#%E9%81%87%E5%88%B0%E7%9A%84%E9%97%AE%E9%A2%98%E5%8F%8A%E8%A7%A3%E5%86%B3%E6%96%B9%E6%A1%88" class="hash-link" aria-label="Direct link to 遇到的问题及解决方案" title="Direct link to 遇到的问题及解决方案">​</a></h3>
<p>我们当前私有云分析集群使用的是 Cloudera CDP，Flink 版本为 Cloudera Version 1.14，整体 Flink 安装目录以及配置文件结构与社区版本有较大出入。直接根据 StreamPark 官方文档进行部署，将无法配置 Flink Home，以及后续整体 Flink 任务提交到集群中，因此需要进行针对化适配集成，在满足使用需求上，尽量提供完整的 StreamPark 使用体验。</p>
<h4 class="anchor anchorWithStickyNavbar_I2Xo" id="flink-集群无法访问"><strong>Flink 集群无法访问</strong><a href="https://realfuture.ai/blog/2024/03/05/#flink-%E9%9B%86%E7%BE%A4%E6%97%A0%E6%B3%95%E8%AE%BF%E9%97%AE" class="hash-link" aria-label="Direct link to flink-集群无法访问" title="Direct link to flink-集群无法访问">​</a></h4>
<p>① 问题描述：Cloudera Flink 的安装路径与实际提交路径不一致，实际提交路径下缺少 conf 目录。</p>
<p>② 解决办法：实际的 flink 提交路径在</p>
<div class="language-shell codeBlockContainer_eR_5 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_jz8P"><pre tabindex="0" class="prism-code language-shell codeBlock_tQzK thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_J4lo"><span class="token-line" style="color:#F8F8F2"><span class="token plain">/opt/cloudera/parcels/Flink-$ {version}/lib/flink/bin/flink</span><br></span></code></pre><div class="buttonGroup_EiCC"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_azoe" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_HjTd"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_dSkr"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>因此路径</p>
<div class="language-shell codeBlockContainer_eR_5 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_jz8P"><pre tabindex="0" class="prism-code language-shell codeBlock_tQzK thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_J4lo"><span class="token-line" style="color:#F8F8F2"><span class="token plain">/opt/cloudera/parcels/Flink-$ {version}/1ib/flink</span><br></span></code></pre><div class="buttonGroup_EiCC"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_azoe" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_HjTd"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_dSkr"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>可以理解为真正的 Flink Home，具体查看该目录下内容。</p>
<div data-rmiz=""><div data-rmiz-content="not-found" style="visibility:visible"><img src="https://realfuture.ai/img/blog/2024-03-05/07.png" alt="07" style="cursor:pointer"></div></div>
<p>发现缺少 conf 目录，倘若配置该目录在 StreamPark 为 Flink Home 将无法访问到集群，因此可软连接 Flink 配置或者在该路径下编辑集群中的 Flink 配置文件。</p>
<div data-rmiz=""><div data-rmiz-content="not-found" style="visibility:visible"><img src="https://realfuture.ai/img/blog/2024-03-05/08.png" alt="08" style="cursor:pointer"></div></div>
<p>综上，前置配置和打包好代码（代码中可能会涉及到自己使用上的优化修改）之后，可以进行部署。</p>
<p>注意 2.0 的版本打包的话直接执行源码中的 build.sh 即可，选择混合部署，生成的包在 dist 目录下。</p>
<h4 class="anchor anchorWithStickyNavbar_I2Xo" id="hadoop-环境检查失败"><strong>Hadoop 环境检查失败</strong><a href="https://realfuture.ai/blog/2024/03/05/#hadoop-%E7%8E%AF%E5%A2%83%E6%A3%80%E6%9F%A5%E5%A4%B1%E8%B4%A5" class="hash-link" aria-label="Direct link to hadoop-环境检查失败" title="Direct link to hadoop-环境检查失败">​</a></h4>
<div data-rmiz=""><div data-rmiz-content="not-found" style="visibility:visible"><img src="https://realfuture.ai/img/blog/2024-03-05/09.png" alt="09" style="cursor:pointer"></div></div>
<div class="language-shell codeBlockContainer_eR_5 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_jz8P"><pre tabindex="0" class="prism-code language-shell codeBlock_tQzK thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_J4lo"><span class="token-line" style="color:#F8F8F2"><span class="token plain">vi /etc/profile</span><br></span></code></pre><div class="buttonGroup_EiCC"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_azoe" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_HjTd"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_dSkr"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>解决办法：在部署 StreamPark 的节点上添加一下 hadoop 环境即可添加</p>
<div class="language-shell codeBlockContainer_eR_5 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_jz8P"><pre tabindex="0" class="prism-code language-shell codeBlock_tQzK thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_J4lo"><span class="token-line" style="color:#F8F8F2"><span class="token plain">export HADOOP_CONF_DIR=/etc/hadoop/conf</span><br></span></code></pre><div class="buttonGroup_EiCC"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_azoe" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_HjTd"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_dSkr"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>source 使其生效，重启 StreamPark 即可。</p>
<h4 class="anchor anchorWithStickyNavbar_I2Xo" id="hdfs-的-flink路径下缺少-lib-目录"><strong>HDFS 的 Flink路径下缺少 lib 目录</strong><a href="https://realfuture.ai/blog/2024/03/05/#hdfs-%E7%9A%84-flink%E8%B7%AF%E5%BE%84%E4%B8%8B%E7%BC%BA%E5%B0%91-lib-%E7%9B%AE%E5%BD%95" class="hash-link" aria-label="Direct link to hdfs-的-flink路径下缺少-lib-目录" title="Direct link to hdfs-的-flink路径下缺少-lib-目录">​</a></h4>
<p>解决办法：在于部署后的 StreamPark 在 HDFS 上的工作目录上 lib 目录没有正常上传，找到 HDFS 上初始化的 StremPark work 路径，观察一下 hdfs:///streampark/flink/.../下的 lib 目录是否完整，不完整的话手动将本地 Flink Home 目录下的 lib put 上去即可。</p>
<div data-rmiz=""><div data-rmiz-content="not-found" style="visibility:visible"><img src="https://realfuture.ai/img/blog/2024-03-05/10.png" alt="10" style="cursor:pointer"></div></div>
<h4 class="anchor anchorWithStickyNavbar_I2Xo" id="作业失败后自动拉起导致作业重复"><strong>作业失败后自动拉起导致作业重复</strong><a href="https://realfuture.ai/blog/2024/03/05/#%E4%BD%9C%E4%B8%9A%E5%A4%B1%E8%B4%A5%E5%90%8E%E8%87%AA%E5%8A%A8%E6%8B%89%E8%B5%B7%E5%AF%BC%E8%87%B4%E4%BD%9C%E4%B8%9A%E9%87%8D%E5%A4%8D" class="hash-link" aria-label="Direct link to 作业失败后自动拉起导致作业重复" title="Direct link to 作业失败后自动拉起导致作业重复">​</a></h4>
<p>StreamPark 自身具备作业使用后重启拉取的能力，当检测到作业失败后会重新拉起，但在实践中发现会出现同一个失败的作业在 YARN上启动多个的情况，经过和社区沟通，已确定是个 Bug，最终在 2.1.3 中解决了该 Bug。</p>
<h2 class="anchor anchorWithStickyNavbar_I2Xo" id="带来的收益"><strong>带来的收益</strong><a href="https://realfuture.ai/blog/2024/03/05/#%E5%B8%A6%E6%9D%A5%E7%9A%84%E6%94%B6%E7%9B%8A" class="hash-link" aria-label="Direct link to 带来的收益" title="Direct link to 带来的收益">​</a></h2>
<p>目前长安汽车已经在云上生产/预生产环境、云下生产/预生产环境中部署了 StreamPark，截至发稿前 StreamPark 共管理了 150+ 的 Flink 作业，包括 JAR 和与 SQL 作业。涉及利用 Flink、FlinkCDC 等技术，从 MySQL 或 kafka 同步数据到 MySQL、Doris、HBase、Hive 等数据库。后续所有环境总计 3000+ 的 Flink 作业也会分批迁至 StreamPark 来集中管理。</p>
<p><strong>Apache StreamPark 最明显的收益是提供了一站式服务。业务开发人员可以在 StreamPark 上完成作业开发、编译和发布，无需再使用多个工具完成一个 Flink SQL 作业的开发，从而简化了整个流程。</strong> StreamPark 为我们节省了大量 Flink 作业开发与部署时间，显著提升了 Flink 应用开发效率。</p>
<div data-rmiz=""><div data-rmiz-content="not-found" style="visibility:visible"><img src="https://realfuture.ai/img/blog/2024-03-05/11.png" alt="11" style="cursor:pointer"></div></div>]]></content:encoded>
            <category>StreamPark</category>
            <category>Engineering</category>
        </item>
        <item>
            <title><![CDATA[联通 Flink 实时计算平台化运维实践]]></title>
            <link>https://realfuture.ai/blog/2023/11/04/</link>
            <guid>https://realfuture.ai/blog/2023/11/04/</guid>
            <pubDate>Sat, 04 Nov 2023 00:00:00 GMT</pubDate>
            <description><![CDATA[联通数科实时计算团队负责人、Apache StreamPark Committer 穆纯进在 Flink Forward Asia 2022 平台建设专场的实践分享。]]></description>
            <content:encoded><![CDATA[<blockquote>
<p>本文整理自联通数科实时计算团队负责人、Apache StreamPark Committer 穆纯进在 Flink Forward Asia 2022 平台建设专场的分享，本篇内容主要分为四个部分：</p>
<ul>
<li>实时计算平台背景介绍</li>
<li>Flink 实时作业运维挑战</li>
<li>基于 StreamPark 一体化管理</li>
<li>未来规划与演进</li>
</ul>
</blockquote>
<!-- -->
<h2 class="anchor anchorWithStickyNavbar_I2Xo" id="实时计算平台背景介绍"><strong>实时计算平台背景介绍</strong><a href="https://realfuture.ai/blog/2023/11/04/#%E5%AE%9E%E6%97%B6%E8%AE%A1%E7%AE%97%E5%B9%B3%E5%8F%B0%E8%83%8C%E6%99%AF%E4%BB%8B%E7%BB%8D" class="hash-link" aria-label="Direct link to 实时计算平台背景介绍" title="Direct link to 实时计算平台背景介绍">​</a></h2>
<div data-rmiz=""><div data-rmiz-content="not-found" style="visibility:visible"><img src="https://realfuture.ai/img/blog/2023-11-04/01.png" alt="01" style="cursor:pointer"></div></div>
<p>上图是实时计算平台的整体架构，最底层是数据源，由于一些敏感信息，没有将数据源的详细信息列出，它主要包含三部分，分别是业务数据库、用户行为日志、用户位置，联通的数据源非常多，业务数据库这一项就有几万张表；主要通过 Flink SQL 和 DataStream API 来处理数据 ，数据处理流程包括 Flink 对数据源的实时解析、规则的实时计算以及实时产品；用户在可视化订阅平台上进行实时数据订阅，用户可以在地图上画一个电子围栏，并设置一些规则，如来自于哪里，在围栏里驻留多长时间等，还可以筛选一些特征，符合这些规则的用户信息会实时进行推送，然后是实时安全部分，当某个用户连接了高危基站或是有异常操作行为时，我们会认为可能存在诈骗行为，会对手机号码进行关停等等，还有用户的一些实时特征以及实时大屏。</p>
<div data-rmiz=""><div data-rmiz-content="not-found" style="visibility:visible"><img src="https://realfuture.ai/img/blog/2023-11-04/02.png" alt="02" style="cursor:pointer"></div></div>
<p>上图是数据处理的详细的流程。</p>
<p>第一部分是采集解析，我们的数据源来自于业务的数据库，包含 OGG 和 DTS 格式的消息、日志消息、用户行为和用户位置数据，总共 50 多种数据源，后续还会逐渐增加，所有数据源均使用 Flink 做实时解析；并增加了 Metrics 来监控数据源的延迟情况。</p>
<p>第二部分是实时计算，这个环节处理的数据量很大，数据量在万亿级别，支撑了 10000+的数据实时订阅，有 200 多个 Flink 任务，我们将某一种同类型的业务封装成一种场景，同一个 Flink 作业可以支持相同场景的多个订阅，目前 Flink 作业数还在不停的增长，后续可能会增加到 500 多个；其中面临的一个很大挑战是每天万亿级的数据实时关联电子围栏、用户特征等信息，电子围栏有几万个，用户特征涉及数亿用户，最初我们将电子围栏信息和用户特征放到 HBase，但这样会导致 HBase 压力很大，经常遇到性能问题造成数据延迟，而且一旦产生数据积压，需要很长的时间去消化，得益于 Flink State 的强大，我们将电子围栏信息和用户特征放到状态里，目前已经很好的支撑了大并发的场景，同时我们也增加了数据处理的性能监控；最后是实时产品和营销触达前端的一些应用。</p>
<div data-rmiz=""><div data-rmiz-content="not-found" style="visibility:visible"><img src="https://realfuture.ai/img/blog/2023-11-04/03.png" alt="03" style="cursor:pointer"></div></div>
<p>2018 年采用了三方黑盒的计算引擎，不能支持灵活定制个性化功能，且依赖过多外部系统，导致外部系统负载高，运维复杂；2019 年使用了 Spark Streaming 的微批处理，2020 年开始使用 Flink 的流式计算，从 2021 年开始，几乎所有 Spark Streaming 的微批处理都被 Flink 替代了，同时上线了 Apache StreamPark 对我们的 Flink 作业进行管理。</p>
<div data-rmiz=""><div data-rmiz-content="not-found" style="visibility:visible"><img src="https://realfuture.ai/img/blog/2023-11-04/04.png" alt="04" style="cursor:pointer"></div></div>
<p>总结一下平台背景，主要包含以下几部分：</p>
<ul>
<li>数据量大：日均万亿的数据处理。</li>
<li>数据源多：集成了 50 多种实时数据源。</li>
<li>订阅多：支撑了 10000+的数据服务订阅。</li>
<li>用户多：支撑了 30 多个内部和外部用户使用。</li>
</ul>
<div data-rmiz=""><div data-rmiz-content="not-found" style="visibility:visible"><img src="https://realfuture.ai/img/blog/2023-11-04/05.png" alt="05" style="cursor:pointer"></div></div>
<p>运维背景也可以分为以下几部分：</p>
<ul>
<li>支撑需求多：50 多种数据源，10000+的数据服务订阅。</li>
<li>实时作业多：现在有 200+ 个 Flink 生产作业，并且持续快速增长，未来可达 500+ 个。</li>
<li>上线频率高：每天都有新增的或增强的 Flink 作业上线操作。</li>
<li>开发人员多：50+研发人员参与开发 Flink 实时计算任务。</li>
<li>使用用户多：30+内部和外部组织的用户使用。</li>
<li>监控延迟低：一旦发现问题我们要立马进行处理，避免引起用户的投诉。</li>
</ul>
<h2 class="anchor anchorWithStickyNavbar_I2Xo" id="flink-实时作业运维挑战"><strong>Flink 实时作业运维挑战</strong><a href="https://realfuture.ai/blog/2023/11/04/#flink-%E5%AE%9E%E6%97%B6%E4%BD%9C%E4%B8%9A%E8%BF%90%E7%BB%B4%E6%8C%91%E6%88%98" class="hash-link" aria-label="Direct link to flink-实时作业运维挑战" title="Direct link to flink-实时作业运维挑战">​</a></h2>
<div data-rmiz=""><div data-rmiz-content="not-found" style="visibility:visible"><img src="https://realfuture.ai/img/blog/2023-11-04/06.png" alt="06" style="cursor:pointer"></div></div>
<p>基于平台和运维背景，尤其是 Flink 作业越来越多的情况下，遇到了很大的挑战，主要有两方面，分别是作业运维困境和业务支撑困境。</p>
<p>在作业运维困境上，首先作业部署流程长、效率低；在联通安全是第一红线下，在服务器上部署程序的时候，要连接 VPN、登录 4A、打包编译、部署、然后再启动，整个流程比较长，最初在开发 Flink 的时候，都是用脚本启动的，导致代码分支是不可控的，部署完之后也难以追溯，再就是脚本很难与 git 上的代码进行同步，因为对于脚本代码，开发人员更喜欢在服务器上直接改，很容易忘记上传 git。</p>
<p>由于作业运维困境上的种种因素，会产生业务支撑困境，如导致上线故障率高、影响数据质量、上线时间长、数据延迟高、告警漏发处理等，引起的投诉，此外，我们的业务影响不明确，一旦出现问题，处理问题会成为第一优先级。</p>
<h2 class="anchor anchorWithStickyNavbar_I2Xo" id="基于-apache-streampark-一体化管理"><strong>基于 Apache StreamPark™ 一体化管理</strong><a href="https://realfuture.ai/blog/2023/11/04/#%E5%9F%BA%E4%BA%8E-apache-streampark-%E4%B8%80%E4%BD%93%E5%8C%96%E7%AE%A1%E7%90%86" class="hash-link" aria-label="Direct link to 基于-apache-streampark-一体化管理" title="Direct link to 基于-apache-streampark-一体化管理">​</a></h2>
<div data-rmiz=""><div data-rmiz-content="not-found" style="visibility:visible"><img src="https://realfuture.ai/img/blog/2023-11-04/07.png" alt="07" style="cursor:pointer"></div></div>
<p>对于以上两种困境，我们基于 StreamPark 一体化管理解决了很多问题。首先来看 StreamPark 的双线演进，分别是 Flink 作业管理和 Flink 作业 DevOps 平台；在作业管理上，StreamPark 支持将 Flink 实时作业部署到不同集群，例如 Flink 原生的 Standalone 模式，Flink on YARN 的 Session、Application、Per-Job 模式，以及 Kubernetes Native Session 模式；中间层包含项目管理、作业管理、集群管理、团队管理、变量管理和告警管理。</p>
<ul>
<li>项目管理：当部署 Flink 程序的时候，可以在项目管理里填写 git 地址，同时选择要部署的分支。</li>
<li>作业管理：可以指定 Flink 作业的执行模式，比如你要提交到什么类型的集群里去，同时还可以配置一些资源，比如 TaskManager 的数量、TaskManager/JobManager 的内存大小、并行度等等，还可以设置一些容错，比如 Flink 作业失败后，StreamPark 可以支持它自动拉起，同时支持传入一些动态参数。</li>
<li>集群管理：可以在界面上添加和管理大数据集群。</li>
<li>团队管理：在企业的实际生产过程中会有多个团队，团队之间是隔离的。</li>
<li>变量管理：可以把一些变量统一维护在一个地方，比如 Kafka 的 Broker 地址定义成一个变量，在配置 Flink 作业或者 SQL 的时候，就可以以变量的方式来替换 Broker 的 IP，且后续这个 Kafka 要下线的时候，也可以通过这个变量去查看到底哪些作业使用了这个集群，方便我们去做一些后续的流程。</li>
<li>告警管理：支持多种告警模式，如微信、钉钉、短信和邮件。</li>
</ul>
<p>StreamPark 支持 Flink SQL 与 Flink JAR 作业提交、资源配置和状态跟踪，并提供指标大屏与日志查看能力。</p>
<div data-rmiz=""><div data-rmiz-content="not-found" style="visibility:visible"><img src="https://realfuture.ai/img/blog/2023-11-04/08.png" alt="08" style="cursor:pointer"></div></div>
<p>Flink 作业 DevOps 平台，主要包括以下几部分：</p>
<ul>
<li>团队：StreamPark 支持多个团队，每个团队都有团队的管理员，他拥有所有权限，同时还有团队的开发者，他只有少量的一部分权限。</li>
<li>编译、打包：在创建 Flink 项目时，可以把 git 地址、分支、打包的命令等配置在项目里，然后一键点击 build 按钮进行编译、打包。</li>
<li>发布、部署：发布和部署的时候会创建 Flink 作业，在 Flink 作业里可以选择执行模式、部署集群、资源设置、容错设置、变量填充，最后通过一键启动停止，启动 Flink 作业。</li>
<li>状态监测：Flink 作业启动完成之后，就是状态的实时跟踪，包括 Flink 的运行状态、运行时长、Checkpoint 信息等，并支持一键跳转到 Flink 的 Web UI。</li>
<li>日志、告警：包含构建的一些日志和启动日志，同时支持钉钉、微信、邮件、短信等告警方式。</li>
</ul>
<div data-rmiz=""><div data-rmiz-content="not-found" style="visibility:visible"><img src="https://realfuture.ai/img/blog/2023-11-04/09.png" alt="09" style="cursor:pointer"></div></div>
<p>企业一般有多个团队同时开发实时作业，在我们公司包含实时采集团队、数据处理团队和实时的营销团队，StreamPark 支持多个团队的资源隔离。</p>
<div data-rmiz=""><div data-rmiz-content="not-found" style="visibility:visible"><img src="https://realfuture.ai/img/blog/2023-11-04/10.png" alt="10" style="cursor:pointer"></div></div>
<p>Flink 作业平台化管理面临如下挑战：</p>
<ul>
<li>脚本数量多：平台有几百个脚本，分散在多个服务器上。</li>
<li>脚本类型多：在启动 Flink 作业时，会有启动脚本、停止脚本和守护脚本，而且操作权限很难控制。</li>
<li>脚本不一致：服务器上的脚本与 git 上的脚本不一致。</li>
<li>脚本确权难：Flink 作业的责任人，用途不明确。</li>
<li>分支不可控：启动作业的时候，需要在脚本里指定 git 分支，导致分支不可追溯的。</li>
</ul>
<p>基于以上的挑战，StreamPark 通过项目管理来解决了责任人不明确，分支不可追溯的问题，因为在创建项目的时候需要手动指定一些分支，一旦打包成功，这些分支是有记录的；通过作业管理对配置进行了集中化，避免了脚本太过于分散，而且作业启动、停止的权限有严格的控制，避免了脚本化权限不可控的状态，StreamPark 以接口的方式与集群进行交互来获取作业信息，这样做会让作业控制更加精细。</p>
<p>可以看一下上图中下面的图，通过项目管理进行打包，通过作业管理进行配置，然后发布，可以进行一键启停，通过 API 提交作业。</p>
<div data-rmiz=""><div data-rmiz-content="not-found" style="visibility:visible"><img src="https://realfuture.ai/img/blog/2023-11-04/11.png" alt="11" style="cursor:pointer"></div></div>
<p>早期部署需要 7 个步骤，包括连接 VPN、登录 4A、执行编译脚本、执行启动脚本、打开 YARN、搜索作业名和进入 Flink UI。StreamPark 提供一键打包、一键发布、一键启动和一键进入 Flink UI 等能力。</p>
<div data-rmiz=""><div data-rmiz-content="not-found" style="visibility:visible"><img src="https://realfuture.ai/img/blog/2023-11-04/12.png" alt="12" style="cursor:pointer"></div></div>
<p>上图展示了 StreamPark 的作业提交流程。StreamPark 发布作业并上传所需资源，随后携带配置参数，通过 Flink Submit 接口将作业提交到集群。不同的 Flink Submit 对应不同执行模式，例如 YARN Session、YARN Application、Kubernetes Session 和 Kubernetes Application。提交后，Flink on YARN 作业会返回 Application ID 或 Job ID，Kubernetes 作业也会返回 Job ID；平台将这些 ID 保存到数据库，用于后续跟踪作业状态。</p>
<div data-rmiz=""><div data-rmiz-content="not-found" style="visibility:visible"><img src="https://realfuture.ai/img/blog/2023-11-04/13.png" alt="13" style="cursor:pointer"></div></div>
<p>对于 Flink on YARN 作业，平台可通过提交时获得的 Application ID 或 Job ID 查询状态。当作业数量较多时，StreamPark 状态获取器每 5 秒通过 ResourceManager 轮询状态，ResourceManager 再访问对应的 JobManager，容易造成连接数压力。</p>
<p>上图中 ResourceManager 的连接数阶段性、周期性的持续走高，可以看到 ResourceManager 处于比较红的状态，从主机上去监控的时候，它的连接数确实比较高。</p>
<div data-rmiz=""><div data-rmiz-content="not-found" style="visibility:visible"><img src="https://realfuture.ai/img/blog/2023-11-04/14.png" alt="14" style="cursor:pointer"></div></div>
<p>针对上面的问题，我们做了一些优化，首先 StreamPark 保存了提交作业之后的 Application ID 或者 Job ID，同时也会获取 Job Manager 直接访问的地址，并保存在数据库中，每次轮询时不再通过 ResourceManager 获取作业的状态，它可以直接调用各个 Job Manager 的地址实时获取状态，极大的降低了 ResourceManager 的连接数；从上图最后的部分可以看到，基本不会产生太大的连接数，大大减轻了 ResourceManager 的压力，且后续当 Flink 作业越来越多时获取状态也不会遇到瓶颈的问题。</p>
<div data-rmiz=""><div data-rmiz-content="not-found" style="visibility:visible"><img src="https://realfuture.ai/img/blog/2023-11-04/15.png" alt="15" style="cursor:pointer"></div></div>
<p>StreamPark 解决的另一个问题是 Flink 从状态恢复的保障，以前我们用脚本做运维的时候，在启动 Flink 的时候，尤其是在业务升级的时候，要从上一个最新的 Checkpoint 来恢复，但经常有开发人员忘记从上一个检查点进行恢复，导致数据质量产生很大的问题，遭到投诉，StreamPark 的流程是在首次启动的时候，每五秒钟轮询一次获取 Checkpoint 的记录，同时保存在数据库之中，在 StreamPark 上手动停止 Flink 作业的时候，可以选择做不做 Savepoint，如果选择了做 Savepoint，会将 Savepoint 的路径保存在数据库中，同时每次的 Checkpoint 记录也保存在数据库中，当下次启动 Flink 作业的时候，默认会选择最新的 Checkpoint 或者 Savepoint 记录，有效避免了无法从上一个检查点去恢复的问题，也避免了导致问题后要进行 offset 回拨重跑作业造成的资源浪费，同时也保证了数据处理的一致性。</p>
<div data-rmiz=""><div data-rmiz-content="not-found" style="visibility:visible"><img src="https://realfuture.ai/img/blog/2023-11-04/16.png" alt="16" style="cursor:pointer"></div></div>
<p>StreamPark 还解决了在多环境下多个组件的引用挑战，比如在企业中通常会有多套环境，如开发环境、测试环境、生产环境等，一般来说每套环境下都会有多个组件，比如 Kafka，HBase、Redis 等，而且在同一套环境里还可能会存在多个相同的组件，比如在联通的实时计算平台，从上游的 Kafka 消费数据的时候，将符合要求的数据再写到下游的 Kafka，这个时候同一套环境会涉及到两套 Kafka，单纯从 IP 很难判断是哪个环境哪个组件，所以我们将所有组件的 IP 地址都定义成一个变量，比如 Kafka 集群，开发环境、测试环境、生产环境都有 Kafka.cluster 这个变量，但它们指向的 Broker 的地址是不一样的，这样不管是在哪个环境下配置 Flink 作业，只要引用这个变量就可以了，大大降低了生产上的故障率。</p>
<div data-rmiz=""><div data-rmiz-content="not-found" style="visibility:visible"><img src="https://realfuture.ai/img/blog/2023-11-04/17.png" alt="17" style="cursor:pointer"></div></div>
<p>StreamPark 支持 Flink 多执行的模式，包括基于 on Yarn 的 Application/ Perjob / Session 三种部署模式，还支持 Kubernetes 的 Application 和 Session 两种部署模式，还有一些 Remote 的模式。</p>
<div data-rmiz=""><div data-rmiz-content="not-found" style="visibility:visible"><img src="https://realfuture.ai/img/blog/2023-11-04/18.png" alt="18" style="cursor:pointer"></div></div>
<p>StreamPark 也支持 Flink 的多版本，比如联通现在用的是 1.14.x，现在 1.16.x 出来后我们也想体验一下，但不可能把所有的作业都升级到 1.16.x，我们可以把新上线的升级到 1.16.x，这样可以很好的满足使用新版本的要求，同时也兼容老版本。</p>
<h2 class="anchor anchorWithStickyNavbar_I2Xo" id="未来规划与演进"><strong>未来规划与演进</strong><a href="https://realfuture.ai/blog/2023/11/04/#%E6%9C%AA%E6%9D%A5%E8%A7%84%E5%88%92%E4%B8%8E%E6%BC%94%E8%BF%9B" class="hash-link" aria-label="Direct link to 未来规划与演进" title="Direct link to 未来规划与演进">​</a></h2>
<div data-rmiz=""><div data-rmiz-content="not-found" style="visibility:visible"><img src="https://realfuture.ai/img/blog/2023-11-04/19.png" alt="19" style="cursor:pointer"></div></div>
<p>未来我们将加大力度参与 StreamPark 建设，以下我们计划要增强的方向。</p>
<ul>
<li>高可用：StreamPark 目前不支持高可用，这方面还需要做一些加强。</li>
<li>状态的管理：在企业实践中 Flink 作业在上线时，每个算子会有 UID。如果 Flink UID 不做设置，做 Flink 作业的升级的时候，就有可能出现状态无法恢复的情况，目前通过平台还无法解决这个问题，所以我们想在平台上增加这个功能，在 Flink Jar 提交时，增加检测算子是否设置 UID 的功能，如果没有，会发出提醒，这样可以避免每次上线 Flink 作业时，作业无法恢复的问题；之前遇到这种情况的时候，我们需要使用状态处理的 API，从原来的状态里进行反序列化，然后再用状态处理 API 去制作新的状态，供升级后的 Flink 加载状态。</li>
<li>更细致的监控：目前支持 Flink 作业失败之后，StreamPark 发出告警。我们希望 Task 失败之后也可以发出告警，我们需要知道失败的原因；还有作业反压监控告警、Checkpoint 超时、失败告警性能指标采集，也有待加强。</li>
<li>流批一体：结合 Flink 流批一体引擎和数据湖流批一体存储探索流批一体平台。</li>
</ul>]]></content:encoded>
            <category>StreamPark</category>
            <category>Engineering</category>
        </item>
    </channel>
</rss>