Apache SeaTunnel 开发规范与 AI Agent 工程实践指南:从构建验证到提交协作的完整约定
【免费下载链接】seatunnelSeaTunnel is a multimodal, high-performance, distributed, massive data integration tool.项目地址: https://gitcode.com/GitHub_Trending/se/seatunnel
Apache SeaTunnel 在仓库根目录维护了一份面向 LLM / AI Agent 的上下文指南(CLAUDE.md,与AGENTS.md内容一致),它把成熟 Apache 项目的工程纪律沉淀为可执行的硬性约定:提变更前必须本地验证、提交信息必须遵循[Type][Module]格式、配置项必须用Option定义、不兼容变更必须登记备案。本文以此文档为骨架,结合仓库源码(seatunnel-api、seatunnel-engine、seatunnel-e2e、bin/install-plugin.sh等)逐条展开解读,帮助你(无论是人还是 Agent)在 SeaTunnel 代码库上写出安全、一致、可验证的代码与提交。
这份文档是什么:为 LLM/Agent 准备的代码库上下文指南
CLAUDE.md的定位非常明确:帮助 AI 助手(LLM / Agent)对 Apache SeaTunnel 代码库做出安全(safe)、一致(consistent)、可验证(verifiable)的修改。它并不是泛泛的贡献指南,而是镜像了成熟 Apache 项目的工程实践,并逐一适配到 SeaTunnel 特有的构建、测试、架构和文档约定上——例如 Zeta 引擎的三层角色、Option配置体系、seatunnel-e2e的 Testcontainers 测试范式等。
因此,理解这份文档的正确方式是把它当作"进入 SeaTunnel 代码库的协作契约":文档中的每一条规则,几乎都能在仓库中找到对应的实现或配套脚本作为证据。
铁律一:提变更前必须本地验证
文档开篇即以 "CRITICAL: Validate Before Proposing Changes" 强调:Agent 必须在本地运行验证命令之后,再建议或提交变更,否则 PR 大概率会被拒绝。
# 格式化代码(强制) ./mvnw spotless:apply # 快速验证(强制) ./mvnw -q -DskipTests verify # 单元测试(强烈建议) ./mvnw test三条命令分工明确:
spotless:apply是 SeaTunnel 的代码格式化入口,统一使用Google Java Format(AOSP 风格)。仓库中tools/spotless_check/pre-commit.sh的存在进一步印证:格式检查被前置到提交阶段,避免不合规代码流入主干。-q -DskipTests verify用于快速验证编译与打包链路是否畅通,跳过测试以节省时间,是"改完先保证能编译"的底线检查。mvnw test运行单元测试,验证行为正确性,属于强烈推荐项。
Git 提交信息约定
SeaTunnel 采用严格的提交信息格式来维持干净、可检索的历史记录:
[Type][Module] DescriptionType(类型):
| Type | 含义 |
|---|---|
Feature | 新功能 |
Fix | Bug 修复 |
Improve | 对现有行为的改进 |
Docs | 仅文档变更 |
Test | 测试用例或测试框架变更 |
Chore | 构建、依赖或维护类任务 |
Module(模块):模块名与仓库顶层目录一一对应,例如:
| Module | 对应模块 |
|---|---|
Connector-V2 | seatunnel-connectors-v2 |
Zeta | seatunnel-engine(Zeta 引擎) |
Core | seatunnel-core |
API | seatunnel-api |
Transform-V2 | seatunnel-transforms-v2 |
Format | seatunnel-formats |
Translation | seatunnel-translation |
E2E | seatunnel-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这种格式让git log --grep可以快速按模块或类型过滤历史,例如查找所有 Zeta 引擎的修复只需要检索\[Fix\]\[Zeta\]。
仓库结构速览
文档给出了模块级的目录导航,与实际仓库布局一一对应:
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/下按连接器拆分出 90+ 个独立模块(connector-jdbc、connector-kafka、connector-cdc-* 等),这正是文档所说"连接器是主要贡献区域"的原因;seatunnel-engine/下则是 Zeta 引擎的 client/common/core/server/storage 等子模块。提交信息中的 Module 名与这套目录体系严格对应。
Java 代码规范
SeaTunnel 后端遵循 Google Java Format(AOSP 风格),由 Spotless 强制实施,此外还有几条硬性约定:
- 导入:禁止通配符导入(
import xxx.*);优先使用 shade 后的依赖,包名为org.apache.seatunnel.shade.*。这一点在 Option.java 中即可看到实例:它导入的是org.apache.seatunnel.shade.com.fasterxml.jackson.core.type.TypeReference,而非直接依赖 Jackson 原始坐标——这正是 shade 依赖隔离策略的落地。 - 空值语义:避免隐式的 null 假设,null 处理必须显式。
- 可见性:API 保持最小化,能包内私有(package-private)就优先,不向外部暴露不必要的接口。
- 注释:重要方法必须写注释,包括 public API、生命周期钩子(初始化、start/stop、checkpoint)以及复杂或性能敏感的逻辑。文档给出了标准示例:
/** * Enumerates source splits for parallel reading. * Called once during job initialization. * * @param context Split enumeration context * @return Collection of discovered splits */ @Override public List<SourceSplit> enumerateSplits(SplitEnumerationContext context) { // Implementation }enumerateSplits正是SeaTunnelSource接口中支撑并行读取的核心方法(见 SeaTunnelSource.java),一次调用返回全部分片,再由引擎分发给多个并行任务。
ASF License 头(强制)
所有新建文件必须携带 ASF 许可证头,这是 Apache 项目的合规红线:
/* * 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. */仓库中几乎每个源码文件与脚本(包括bin/install-plugin.sh、config/v2.batch.config.template等)都以该头开场,新建文件照此复制即可。
向后兼容是硬约束
文档用 "VERY IMPORTANT" 强调:向后兼容是硬约束(hard constraint),Agent 必须将其作为不可逾越的红线。
禁止事项:
- 不得移除或重命名现有配置项(config option)
- 不得随意修改默认值
- 不得破坏 public API 或 SPI 契约
任何不兼容变更必须同时满足:
- 显式写入文档
- 登记到
docs/en/introduction/concepts/incompatible-changes.md - 提供迁移指引
- 在 PR 描述中清晰说明
这份登记文件在仓库中真实存在且持续维护:incompatible-changes.md 记录了逐版本的破坏性变更,例如:
- JDBC 连接器:时区感知时间戳列(MySQL
TIMESTAMP、PostgreSQLtimestamptz等)由统一映射为TIMESTAMP改为显式映射为TIMESTAMP_TZ,直接影响 Iceberg 等下游的建表语义; - 引擎 REST 指标:表级指标 key 从
{tableName}变为{VertexIdentifier}.{tableName}(如Sink[0].fake.user_table),要求 Grafana/Prometheus 监控规则同步更新; Condition.of(option, null)不再被允许:seatunnel-api的Condition构造器现在会在构造期对空期望值抛IllegalArgumentException,官方建议用Conditions.notBlank(option)替代。
这些真实条目告诉我们:兼容性管理不是口号,而是有制度化登记、有迁移方案、有影响评估的完整流程。升级前查阅该文件是 SeaTunnel 社区的既定动作。
依赖规则
依赖引入是 Agent 最容易"顺手"触发的改动,文档对此明确设限:
- 除非绝对必要,不得引入新依赖
- 优先复用
org.apache.seatunnel.shade.*下已有的 shade 依赖 - 任何新依赖必须:在 PR 描述中说明理由,并评估 shading、体积与冲突风险
其背后逻辑是:SeaTunnel 通过 shade 把常用三方库(如 Jackson)统一隔离到内部命名空间,避免连接器各自拉版本造成类冲突。读者在阅读连接器代码时,如果看到org.apache.seatunnel.shade.*的 import,应理解为这是刻意的隔离设计,而不是"包名写错了"。
架构指南
Connector(V2)
新连接器的开发必须遵循以下骨架:
- 实现
SeaTunnelSource或SeaTunnelSink接口(定义见 SeaTunnelSource.java) - 配置项使用
Option定义(见下文"配置规则") - 通过
SourceSplitEnumerator支持并行:先枚举分片,再由多个并行 reader 消费 - 禁止把连接器特有的逻辑泄漏到引擎或 core 模块中
这是"插件化"的核心约束:连接器与引擎之间只通过 API 契约通信,引擎不感知任何具体连接器的实现细节,从而保证新增一个连接器无需改动引擎代码。
Zeta 引擎
Zeta 是 SeaTunnel 自研的分布式引擎(seatunnel-engine/),文档明确了三层角色划分:
- Client:提交作业配置
- Master:调度与协调
- Worker:执行任务(Source → Transform → Sink)
这三层在seatunnel-engine/下对应 seatunnel-engine-client、seatunnel-engine-server(含 master/worker 实现)等模块。开发时必须尊重任务边界与生命周期语义——例如 checkpoint 的协调由引擎负责,连接器只负责在prepareCommit/commit等生命周期钩子中完成自身职责。
配置(Option)规则
SeaTunnel 的全部用户可见配置必须通过Option机制定义,这是配置体系的基石。每个 Option 必须包含:
- name(键名)
- type(类型)
- default value(默认值,如适用)
- clear description(清晰描述)
查看 Option.java 的源码即可印证其设计:Option<T>封装了key(配置键)、typeReference(类型引用)、defaultValue(默认值)、description(描述)以及fallbackKeys(回退键列表)五个核心字段。fallbackKeys的存在说明 SeaTunnel 支持配置键的兼容回退——老键名可以平滑映射到新键名,这正是"Option 名称是稳定契约"这一规则的技术支撑。
配套的OptionRule(见 OptionRule.java)负责组装与校验配置项,连接器通过它声明必填项、可选项及条件约束。实际配置模板(如 v2.batch.config.template)中的env/source/sink三段结构,最终都会解析并绑定到各插件声明的 Option 上。
错误处理与日志
- 异常必须携带足够的上下文信息(涉及的表、任务、配置键),方便定位问题
- 禁止吞掉异常(swallow),异常要么向上传播要么显式处理
- 日志级别使用规范:
INFO—— 生命周期事件WARN—— 可恢复问题ERROR—— 导致任务失败的错误
- 绝不记录敏感信息(密码、token、凭据)
这条规则直接关系到可观测性与安全性:CDC 作业中若异常只报"操作失败"而不带表名和任务 ID,排障成本会成倍上升;而日志中混入数据库密码则可能造成生产事故。在实现连接器时,异常消息建议形如"Failed to write to table {table} in task {task}, config key: {key}"。
文档规则
文档被视为功能的一部分,而不是事后的补充("Documentation is part of the feature, not an afterthought"):
- 任何用户可见的变更都必须同步更新
docs/en与docs/zh(仓库中这两套文档目录结构一一对应,正是为了支持双语同步) - 配置名、默认值、示例必须与代码严格一致,禁止文档与实现脱节
- 这意味着 Agent 改配置项时,必须同步检查 docs/en 与 docs/zh 下对应连接器文档中的参数表
测试指南
单元测试
- 位于各模块的
src/test/java下(例如 seatunnel-api 的测试) - 验证行为而非实现细节
- 优先编写确定性、最小化的测试
./mvnw testE2E 测试
- 位于
seatunnel-e2e目录 - 基于Testcontainers拉起真实中间件
- 测试类需继承
TestSuiteBase(基类实现在 TestSuiteBase.java)
./mvnw -DskipUT -DskipIT=false verify注意-DskipUT跳过单元测试、-DskipIT=false开启集成测试,与单测命令形成互补。seatunnel-e2e/seatunnel-connector-v2-e2e/下每个连接器都有对应的connector-xxx-e2e模块,例如 connector-jdbc-e2e、connector-cdc-mysql-e2e 等,它们是连接器改动合入前的最后一道防线。
性能意识
Agent 编写代码时必须评估性能影响:
- 热路径(每条数据都会经过的路径)避免不必要的对象创建——例如在 source/sink 的逐行处理逻辑中重复 new 对象会显著拉高 GC 压力
- 谨慎使用大内存缓冲区,警惕 OOM 与背压问题
- 时刻考虑并行度与资源使用:
parallelism的取值、分片粒度的设计都会直接影响集群吞吐
PR 范围规则
- 变更保持最小化与聚焦
- 避免夹带无关重构或纯格式修改
- 一个 PR 只解决一个问题
这条规则与"向后兼容硬约束"配合使用:范围越小,review 越容易,回归风险越低,也越容易被 maintainer 接受。
运行与调试实战
从源码构建
./mvnw clean install -DskipTests -Dskip.spotless=true跳过测试与格式检查以加速本地开发迭代;正式提 PR 前仍需补跑前文的验证三连。
安装连接器插件
sh bin/install-plugin.sh $current_version该脚本在仓库 bin/install-plugin.sh 中真实存在,其工作机制值得深入理解:
- 读取清单:脚本读取 config/plugin_config 中
--connectors-v2--标记下的连接器 artifactId 列表,逐一下载(文件头部注释说明了该清单用于把用户配置中的插件名映射到对应 JAR 包名)。 - 版本与下载方式:连接器默认版本为
3.0.0(见 install-plugin.sh),可通过第一个参数覆盖;下载方式由环境变量SEATUNNEL_PLUGIN_DOWNLOAD_METHOD控制(https或maven),当版本为快照/动态版本(如*-SNAPSHOT、LATEST)时自动切换到 Maven 方式以解析唯一快照;Maven 仓库地址可用SEATUNNEL_MAVEN_REPOSITORY覆盖。 - 安全校验:HTTPS 方式下会下载
.sha512/.sha1校验文件并逐字节比对,还会校验下载文件是否为合法 JAR(检查 ZIP 魔数504b),防止下载到损坏或伪造的文件。
运行作业(Zeta)
sh bin/seatunnel.sh --config config/v2.batch.config.template -e local说明:当前源码仓库的bin/目录直接保留的是插件安装脚本(install-plugin.sh及其 Windows 版install-plugin.cmd);seatunnel.sh等启动脚本随发行装配产出,此处沿用CLAUDE.md中面向发行版的标准用法。-e local表示以本地模式运行,作业配置取自仓库中的 v2.batch.config.template,该模板展示了最小可用配置的三段式结构:
env { parallelism = 2 job.mode = "BATCH" checkpoint.interval = 10000 } source { FakeSource { parallelism = 2 plugin_output = "fake" row.num = 16 schema = { fields { name = "string" age = "int" } } } } sink { Console { } }env:作业级配置,parallelism控制并行度,job.mode区分 BATCH/STREAMING,checkpoint.interval设置检查点间隔;source:数据源,FakeSource是内置测试源,row.num控制生成行数,schema声明字段类型;sink:数据目的地,Console把结果打印到控制台,便于快速验证管道连通性。
替换 source/sink 为真实连接器(如 Kafka、JDBC、MySQL CDC)即可过渡到生产场景。
总结:Agent 协作的黄金流程
把整份指南压缩成一份可执行的行动清单,无论对人还是对 Agent 都适用:
- 动手前:阅读
CLAUDE.md/AGENTS.md,对照仓库结构确认改动落在哪个模块; - 写代码时:遵守 Java 规范(Spotless 格式、无通配符 import、shade 依赖)、携带 ASF License 头、用
Option定义配置、按 INFO/WARN/ERROR 分级打日志且不记录敏感信息、保持向后兼容; - 改动后:依次执行
./mvnw spotless:apply→./mvnw -q -DskipTests verify→./mvnw test;连接器改动补 E2E 测试(继承TestSuiteBase); - 提交时:使用
[Type][Module] Description格式,保持一个 PR 解决一个问题; - 若涉及破坏性变更:同步更新
docs/en与docs/zh,登记到 incompatible-changes.md 并提供迁移指引。
这套约定之所以被反复强调,是因为它直接决定了 SeaTunnel 这样一个多模块、多连接器、多引擎适配的大型数据集成项目能否长期保持可维护性。理解并遵守它,是成为合格 SeaTunnel 贡献者的第一步。
【免费下载链接】seatunnelSeaTunnel is a multimodal, high-performance, distributed, massive data integration tool.项目地址: https://gitcode.com/GitHub_Trending/se/seatunnel
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考