Sink Connector 开发指南
目标
这篇文档是面向贡献者实现 SeaTunnel sink connector 的实操入口,重点放在编码前该做哪些设计判断,以及评审时应重点看什么。
Sink 开发为什么更难
Sink 通常比 Source 更难做好,因为它面对的是外部副作用。
一个 sink connector 必须先把自己的语义讲清楚:
- 是 append-only、at-least-once,还是更强的一致性语义
- commit 是幂等的还是依赖事务
- insert、update、delete 怎么处理
- 目标系统对 schema 的兼容边界是什么
如果这些语义没有写清楚,这个 connector 很容易在 demo 场景里看起来没问题,但一到 retry 或恢复场景就出错。
推荐开发流程
1. 先定义写入契约
在开始实现之前,先说明清楚:
- 目标系统模型是 append、overwrite、upsert,还是表级事务提交
- 是否依赖主键
- 是否支持 delete
- 如何处理 schema evolution
- 失败和重试时的行为是什么
这些内容应该同时体现在文档和代码中。
2. 定义稳定的 Options
Sink factory 应该清晰定义:
- required options
- optional options
- default value
- mutually exclusive 或 bundled 规则
不要把 option 名当成临时实现细节,它们是用户可见契约。
相关文档:
3. 先选提交模型
SeaTunnel 的 sink 设计支持多种复杂度层级:
- 只有 writer
- writer + committer
- writer + committer + aggregated committer
应该根据目标系统特性来选,不要默认套最复杂,也不要为了省事牺牲正确性。
4. 实现运行时与打包
一个完整的 sink connector 贡献通常包括:
- sink factory
SeaTunnelSinkSinkWriter- 可选的
SinkCommitter - 可选的
SinkAggregatedCommitter - 打包与发现元数据
5. 验证恢复行为
不要在 happy path 写入成功后就停下。还应该确认这些情况:
prepareCommit之后任务失败会怎样- commit 被重试会怎样
- sink 收到重复 commit 请求会怎样
- 目标表 schema 变化后会怎样
设计检查清单
编码前,建议先回答这些问题:
- 这个 sink 是 append-only 还是 CDC-aware
- 目标系统是否支持幂等 upsert
- 是否需要透传 delete
- exactly-once 风格提交是否依赖事务
- checkpoint 恢复后要恢复哪些状态
- 同一个 commit 被重放两次会发生什么
典型类结构
connector-<name>/
src/main/java/.../sink/
<Name>SinkFactory.java
<Name>Sink.java
<Name>SinkWriter.java
<Name>SinkConfig.java
根据语义复杂度,通常还会补这些类:
<Name>CommitInfo<Name>WriterState<Name>SinkCommitter<Name>SinkAggregatedCommitter- schema 或 table 辅助类
提交模型选择
只有 Writer
适用于:
- at-least-once 或更弱语义可以接受
- 目标系统天然支持幂等
- 不需要集中式 commit 协调
Writer + Committer
适用于:
- 每个 writer 独立 prepare 自己的结果
- commit 可以按 writer 或 partition 分别进行
- 需要显式集中处理 retry
Writer + Aggregated Committer
适用于:
- sink 需要单一的表级或全局 commit 点
- 所有 writer 的输出必须先汇总再整体可见
- 故障处理需要全局协调
对表类 sink 和强一致性场景,这种模型尤其重要。
CDC-Aware Sink 设计
如果 sink 接受 CDC 输入,必须把映射规则写清楚:
- insert -> ?
- update -> ?
- delete -> ?
同时还要明确:
- 是否要求主键
- schema change 是否自动应用
- 对不支持的 row kind,是拒绝、忽略,还是要求上游先做转换
相关文档:
常见坑点
在 prepareCommit 里直接做最终提交
除非你明确设计的是更简单的语义并已写进文档,否则 prepareCommit 不应该偷偷变成真正的最终 commit 点。
Retry 不是幂等的
如果 commit 在失败后会再次执行,重复副作用不能把目标系统写坏。
隐藏语义边界
如果 sink 不支持 delete、schema evolution 或 exactly-once 风格恢复,应该在文档里明确写出来,而不是让用户靠试错发现。
测试策略
至少建议覆盖:
- option 校验
- writer 行为
- prepare commit 行为
- retry 与幂等行为
- checkpoint 或重启后的恢复
如果这个 sink 是生产常用 connector,强烈建议补 E2E 覆盖。
打包检查清单
提交 PR 前建议确认:
- factory 注册已存在
- connector 已加入打包
- 需要时已更新 plugin mapping 与依赖目录布局
- 文档示例与真实 plugin identifier 一致
- 中英文文档都已更新
推荐阅读顺序
- 先读本页,建立设计检查表
- 再读 Sink 架构
- 再读 Exactly-Once
- 再读 插件发现与类加载
- 最后结合 开发自己的 Connector