Apache SeaTunnel 协作开发指南:基于 AGENTS.md 的提交规范、代码标准与工程实践全解析
2026/9/16 6:42:52 网站建设 项目流程

Apache SeaTunnel 协作开发指南:基于 AGENTS.md 的提交规范、代码标准与工程实践全解析

【免费下载链接】seatunnelSeaTunnel is a multimodal, high-performance, distributed, massive data integration tool.项目地址: https://gitcode.com/GitHub_Trending/se/seatunnel

本指南以仓库根目录的 AGENTS.md(LLM Context Guide for Apache SeaTunnel)为核心骨架,系统讲解面向 AI 助手与人类开发者共同遵守的 SeaTunnel 协作契约:从提交前验证、Git 提交信息规范、Java 代码标准、向后兼容性硬约束,到架构准则、测试与调试流程。结合仓库中的 pom.xml、SeaTunnelSource.java、Option.java 等源码证据,帮助读者在提交 PR 时一次通过评审,并为希望用 AI Agent 辅助贡献代码的团队提供可直接落地的工程规范模板。

一、为什么需要 AGENTS.md:LLM 时代的工程协作契约

Apache SeaTunnel 是一个多模态、高性能、分布式的海量数据集成工具,代码库横跨 seatunnel-api、seatunnel-connectors-v2、seatunnel-engine(Zeta 引擎)、seatunnel-transforms-v2 等十余个核心模块。当越来越多的 AI 助手(LLM / Agent)参与代码生成与修改时,如何保证它们产出的代码安全、一致、可验证,就成了社区治理的核心问题。

AGENTS.md 正是为此而生:它借鉴了成熟 Apache 项目的实践,并将其适配到 SeaTunnel 的构建、测试、架构与文档约定上。它不只约束人类开发者,更是一份可被 Agent 直接读取、执行的"机器可读工程规范"。对贡献者而言,理解这份文件等于理解了 SeaTunnel 社区对"一个合格 PR"的全部隐性要求。

二、提交前必须通过的三道验证关卡

AGENTS.md 开篇即给出CRITICAL 级要求:Agent 在提议或定稿任何改动之前,必须在本地运行验证命令。未满足这些要求的 PR 极有可能被直接拒绝。

# 格式化代码(强制) ./mvnw spotless:apply # 快速验证(强制) ./mvnw -q -DskipTests verify # 单元测试(强烈建议) ./mvnw test

三道关卡的定位各不相同:

命令阶段作用
./mvnw spotless:apply格式化统一全仓库代码风格,消除格式差异造成的评审噪音
./mvnw -q -DskipTests verify构建验证跳过测试、快速确认编译与打包链路畅通
./mvnw test单元测试验证行为正确性,防止回归

源码佐证:Spotless 到底在强制什么

在根 pom.xml 中,spotless-maven-plugin(版本 2.29.0)被绑定到validate阶段的spotless-check执行目标,也就是说每次构建都会自动检查代码格式,不通过即构建失败。其 Java 配置严格定义了 SeaTunnel 的编码风格:

  • 格式化引擎:Google Java Format 1.7,风格为AOSP
  • 自动清理removeUnusedImports删除未使用的导入;
  • 导入排序:强制顺序为org.apache.seatunnel.shadeorg.apache.seatunnelorg.apache→ 其他 →javaxjava→ 静态导入;
  • 正则化替换:删除通配符导入(wildcard imports)、封禁org.powermock.*、封禁非 JUnit 5 的 JUnit 4 导入(org.junit.[^jupiter]),并将 Guava、Jetty、Hikari、Janino、Apache Commons Lang3 的导入自动改写为 shade 版本(如com.google.common.*org.apache.seatunnel.shade.com.google.common.*)。

这意味着即使你手写了import java.util.*spotless:apply也会自动修正;而spotless:check则保证 CI 中永远只存在符合规范的代码。

三、Git 提交信息规范:可搜索历史的基石

SeaTunnel 采用严格的提交信息格式来维护干净、可检索的提交历史,格式为:

[类型][模块] 描述

类型(Type)

类型含义
Feature新功能
FixBug 修复
Improve对现有行为的改进
Docs仅文档变更
Test测试用例或测试框架变更
Chore构建、依赖或维护任务

模块(Module)

模块标识对应代码库目录
Connector-V2seatunnel-connectors-v2
Zetaseatunnel-engine(Zeta 引擎)
Coreseatunnel-core
APIseatunnel-api
Transform-V2seatunnel-transforms-v2
Formatseatunnel-formats
Translationseatunnel-translation
E2Eseatunnel-e2e

官方示例

[Fix][Connector-V2] Fix MySQL source split enumeration bug [Fix][Zeta] Fix checkpoint timeout under heavy backpressure [Feature][Transform-V2] Add LLM transform plugin [Improve][Core] Optimize jar package loading speed [Docs] Update quick start guide

从示例可以看出两个要点:一条提交只做一件事;描述采用"动词 + 宾语"的祈使句风格,精准点明改动位置与意图。这与后文的 PR Scope Rule 一脉相承。

四、仓库结构速览:模块地图

AGENTS.md 给出了顶层模块地图,与当前仓库实际目录一一对应:

seatunnel/ ├── seatunnel-api/ # 核心 API 定义 ├── seatunnel-connectors-v2/ # Source & Sink 连接器(主要贡献区域) ├── seatunnel-transforms-v2/ # Transform 插件(含 LLM) ├── seatunnel-engine/ # Zeta 引擎 & Web UI ├── seatunnel-core/ # 作业提交与 CLI 入口 ├── seatunnel-translation/ # Flink & Spark 适配层 ├── seatunnel-formats/ # 数据格式(JSON、Avro 等) ├── seatunnel-e2e/ # 端到端集成测试 ├── docs/ # 文档(en 与 zh 双语) └── config/ # 默认配置

理解这张地图的意义在于:任何改动都应落在正确的模块内。例如新增一个连接器,你的代码主体属于seatunnel-connectors-v2;而如果改动涉及作业提交入口,则应定位到seatunnel-core。架构准则一节会进一步解释为什么这条边界如此重要。

五、Java 代码标准:从格式到设计

5.1 核心规则清单

  • 格式化:Google Java Format(AOSP 风格),由 Spotless 强制执行(见上文 pom.xml 证据);
  • 导入
    • 禁止通配符导入;
    • 使用 shade 依赖:org.apache.seatunnel.shade.*
  • 可空性:避免隐式空值假设,null 语义要显式表达;
  • 可见性:保持 API 最小化,能包级私有(package-private)就优先包级私有;
  • 注释:重要方法必须添加注释——包括 public API、生命周期钩子(初始化、start/stop、checkpoint)、以及复杂或性能关键的逻辑。

5.2 注释规范示例

AGENTS.md 给出了 Source Split 枚举方法的注释模板,该示例在仓库中有完全对应的真实接口。见 SeaTunnelSource.java 中createEnumerator的 Javadoc:

/** * Create source split enumerator, used to generate splits. This method will be called only once * when start a source. * * @param enumeratorContext enumerator context. * @return source split enumerator. * @throws Exception when create enumerator failed. */ SourceSplitEnumerator<SplitT, StateT> createEnumerator( SourceSplitEnumerator.Context<SplitT> enumeratorContext) throws Exception;

这种"先写清契约(何时调用、参数含义、返回值、异常),再写实现"的注释风格,正是评审者与后续维护者最需要的信息。

六、ASF License 头:所有新文件的硬性要求

所有新增文件必须包含 Apache Software Foundation 许可证头(NOTICE 与 LICENSE 共同构成合规基础),完整模板如下:

/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */

该头在仓库每个.java文件的顶部均可看到,例如上文引用的 SeaTunnelSource.java 与 Option.java 都完整携带此头。缺少 License 头的文件在提交时会被社区工具链标记,属于一票否决项

七、向后兼容性:硬约束(VERY IMPORTANT)

AGENTS.md 将向后兼容性定义为硬约束(hard constraint),Agent 与开发者都必须遵守:

  • 禁止删除或重命名现有配置项(Option);
  • 禁止随意修改默认值;
  • 禁止破坏公共 API 或 SPI 契约。

任何不兼容变更必须同时满足四点:

  1. 被显式记录在文档中;
  2. 记录在 docs/en/introduction/concepts/incompatible-changes.md;
  3. 包含迁移指南(migration guidance);
  4. 在 PR 描述中清晰说明。

仓库实践:incompatible-changes.md 的用法

该文档按版本记录所有不兼容更新,升级前必须先检查。以当前仓库中记录的一条 JDBC 变更为例(见 incompatible-changes.md),其标准结构是:

  • Affected componentseatunnel-connectors-v2/connector-jdbcsink exactly-once XA 路径;
  • Description:恢复逻辑改为消费max_commit_attempts、fail-closed 处理 XID 缺口;
  • Impact:依赖旧恢复语义的任务可能在新版本恢复时失败;
  • Migration Guide:升级前检查资源管理器中悬挂的 prepared XA 事务(如 MySQL 的XA RECOVER、PostgreSQL 的pg_prepared_xacts),并协调外部清理动作与作业恢复的时序。

另一个例子是表级监控指标键格式从{tableName}变更为{VertexIdentifier}.{tableName}(如Sink[0].fake.user_table),影响 Grafana 面板与 Prometheus 告警规则——这类对运行期可观测性的破坏同样被显式登记(见同文件### API Changes一节)。

这套机制保证了:破坏性变更永远有迹可循、有据可迁,不会在升级时"静默爆炸"。

八、依赖规则:能不引入就不引入

  • 禁止无充分理由引入新依赖;
  • 优先复用org.apache.seatunnel.shade.*下已有的 shade 依赖;
  • 任何新依赖必须:
    • 在 PR 描述中说明理由;
    • 评估 shading、体积与冲突风险。

这一规则与 Spotless 的导入改写规则(第五节)互为表里:仓库刻意将 Guava、Jetty、Hikari、Commons Lang3 等常用库统一收编到org.apache.seatunnel.shade命名空间,目的就是收敛依赖版本、消除类冲突——这是大数据组件生态里最常见的"依赖地狱"来源。新增依赖时若与已有 shade 库功能重叠,评审几乎必然要求改用现成 shade 版本。

九、架构准则:连接器与 Zeta 引擎的边界

9.1 连接器(Connector V2)开发准则

  • 实现SeaTunnelSourceSeaTunnelSink接口;
  • 使用Option定义配置;
  • 通过SourceSplitEnumerator支持并行度;
  • 禁止将连接器特定逻辑泄漏到引擎或 core 层。

以 SeaTunnelSource.java 为例,该接口同时继承SerializablePluginIdentifierInterfaceSeaTunnelPluginLifeCycleSeaTunnelJobAware,其核心方法分工清晰:

方法职责
getBoundedness()返回数据源的有界性(BATCH / STREAMING)
getProducedCatalogTables()输出 CatalogTable 元数据,替代已废弃的getProducedType()
createReader(...)创建用于产出数据的 SourceReader
getSplitSerializer()序列化/反序列化 Split,默认DefaultSerializer
createEnumerator(...)创建 Split 枚举器,仅在 Source 启动时调用一次

对应地,SeaTunnelSink.java 定义了 Sink 侧契约。**"连接器逻辑不进引擎"**这条边界保证了:新增一个连接器不需要改动 Zeta 引擎一行代码,引擎只依赖seatunnel-api中的 SPI 契约。

9.2 Zeta 引擎三角色模型

AGENTS.md 明确了 Zeta 引擎(seatunnel-engine)的角色分工:

  • Client:提交作业配置;
  • Master:调度与协调;
  • Worker:执行任务(Source → Transform → Sink)。

这三个角色对应 seatunnel-engine 下的 client / server 等子模块,任务边界与生命周期语义必须被严格遵守——例如 checkpoint 的触发与恢复逻辑归属引擎层,连接器只通过 SPI 暴露状态快照接口。

十、配置(Option)规则:稳定契约的基石

所有面向用户的配置必须使用Option定义,且每个 Option 必须包含:

  • name(名称)
  • type(类型)
  • default value(默认值,如适用)
  • description(清晰描述)

Option 名称是稳定契约,不得随意重命名。

源码佐证:Option 类的字段设计

Option.java 的字段恰好对应上述四项要求:

public class Option<T> { /** The current key for that config option. */ private final String key; /** Type of the value that this Option describes. */ private final TypeReference<T> typeReference; /** The default value for this option. */ private final T defaultValue; /** The description for this option. */ String description = ""; @Getter private final List<String> fallbackKeys; ... }

值得关注的是fallbackKeys字段与withFallbackKeys(...)方法:它允许一个 Option 携带回退键,这是实现"旧配置名 → 新配置名"平滑迁移的机制——旧键仍可被识别,从而在重命名配置时不必破坏向后兼容(呼应第七节)。当配置语义变化时,正确做法是保留旧 Option 键并通过 fallback 过渡,而非直接删除。

十一、错误处理与日志规范

  • 异常必须携带足够上下文(表名、任务、配置键);
  • 禁止吞掉异常(swallow exceptions);
  • 日志级别使用规范:
    • INFO—— 生命周期事件;
    • WARN—— 可恢复问题;
    • ERROR—— 会导致任务失败的错误;
  • 绝不记录敏感信息(密码、令牌、凭据)。

这条规则在连接器与引擎的错误路径中随处可见:例如 CDC 连接器的 DDL 解析错误处理变更(见 incompatible-changes.md)——DDL 解析器内部错误不再被吞掉,而是作为解析失败向上传播,避免 CDC 作业静默跳过 schema 变更。这正是"异常必须暴露而非吞掉"原则的活案例。

十二、文档规则:文档是功能的一部分

任何用户可见的变更必须同步更新

  • docs/en(英文文档)
  • docs/zh(中文文档)

并且:配置名、默认值、示例必须与代码严格一致;文档是功能的一部分,而不是事后的补充说明("Documentation is part of the feature, not an afterthought")。

这一规则与第七节的兼容性登记(incompatible-changes.md位于 docs/en/introduction/concepts/incompatible-changes.md)形成闭环:代码变更 → 双语文档更新 → 破坏性变更登记。对 Agent 而言,生成代码却不同步更新docs/endocs/zh,属于必然被打回的缺陷。

十三、测试指南:单元测试与 E2E 测试

13.1 单元测试

  • 位于各模块src/test/java下;
  • 验证行为而非实现细节;
  • 优先确定性、最小化的测试。

运行命令:

./mvnw test

13.2 E2E 测试

  • 位于 seatunnel-e2e 目录;
  • 使用Testcontainers拉起真实依赖(数据库、消息队列等);
  • 测试类继承TestSuiteBase

运行命令(跳过单测、只跑集成测试):

./mvnw -DskipUT -DskipIT=false verify

TestSuiteBase位于 seatunnel-e2e/seatunnel-e2e-common/src/test/java/org/apache/seatunnel/e2e/common/TestSuiteBase.java,它是所有连接器 E2E 测试的公共基类,负责容器生命周期管理与测试环境搭建。以连接器为例,seatunnel-e2e 下每个connector-xxx-e2e模块即为对应连接器的集成测试工程,例如 connector-jdbc-e2e 下有 60+ 个 Java 测试文件,覆盖各数据库方言。

十四、性能意识与 PR 范围

性能意识

Agent 与开发者在任何改动中都必须考虑性能影响:

  • 避免在热路径(hot paths)中创建不必要的对象;
  • 谨慎使用大内存缓冲区;
  • 考虑并行度与资源使用。

SeaTunnel 作为数据集成引擎,Source/Sink 的每行数据处理都在热路径上,微小的分配开销会被数据量放大成可观测的吞吐损失。仓库还提供了 seatunnel-benchmarks(JMH 基准测试)与 tools/benchmarks 脚本,用于量化这类影响。

PR Scope Rule

  • 保持改动最小且聚焦
  • 避免无关的重构或纯格式化改动;
  • 一个 PR 只解决一个问题

这与第三节"一条提交只做一件事"相呼应,是 SeaTunnel 社区评审效率高的根本原因之一。

十五、运行与调试:从源码构建到跑通作业

15.1 从源码构建

./mvnw clean install -DskipTests -Dskip.spotless=true

注意:跳过测试(-DskipTests)与跳过格式检查(-Dskip.spotless=true)通常用于本地快速构建;正式提交前仍应按第二节要求补跑完整验证。

15.2 安装连接器

sh bin/install-plugin.sh $current_version

该脚本按当前版本将连接器插件安装到运行环境(插件清单可参考根目录 plugin-mapping.properties)。

15.3 以 Zeta 模式运行作业

sh bin/seatunnel.sh --config config/v2.batch.config.template -e local

其中-e local表示以本地(单机)模式执行,--config指向作业配置。仓库自带的示例配置 config/v2.batch.config.template 展示了最小可运行结构:

env { # You can set SeaTunnel environment configuration here parallelism = 2 job.mode = "BATCH" checkpoint.interval = 10000 } source { FakeSource { parallelism = 2 plugin_output = "fake" row.num = 16 schema = { fields { name = "string" age = "int" } } } }

FakeSource是仅用于测试与演示的假数据源,配合 Console Sink 即可在不依赖任何外部系统的情况下验证引擎全链路(Source → Transform → Sink)。流式版本可参考 config/v2.streaming.conf.template。

十六、给 Agent 与贡献者的行动清单

把 AGENTS.md 的全部约束浓缩为一次贡献的完整流程:

  1. 动工前:明确改动所属模块(第四节的模块地图),确认接口契约(第九节的 SPI 边界);
  2. 编码中:遵守 Java 规范(第五节)、携带 License 头(第六节)、使用Option定义配置(第十节)、按规范记录日志(第十一节);
  3. 验证:依次执行./mvnw spotless:apply./mvnw -q -DskipTests verify./mvnw test(第二节),连接器改动还应补充 E2E 测试(第十三节);
  4. 兼容性:自检是否触碰了"删除/重命名配置、改默认值、破 SPI"三条红线(第七节),必要时登记到 incompatible-changes 文档并附迁移指南;
  5. 提交:按[Type][Module] Description格式书写提交信息(第三节);
  6. PR:保持范围最小(第十四节),在描述中说明依赖与性能考量,并同步更新 docs/en 与 docs/zh(第十二节)。

遵循这套流程产出的 PR,无论在人类评审还是 CI 检查面前,都能以最低的沟通成本快速通过——这正是 AGENTS.md 作为"LLM 时代的工程协作契约"的核心价值。

【免费下载链接】seatunnelSeaTunnel is a multimodal, high-performance, distributed, massive data integration tool.项目地址: https://gitcode.com/GitHub_Trending/se/seatunnel

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询