跳到主要内容
版本:Next

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
  • SeaTunnelSink
  • SinkWriter
  • 可选的 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 一致
  • 中英文文档都已更新

推荐阅读顺序

  1. 先读本页,建立设计检查表
  2. 再读 Sink 架构
  3. 再读 Exactly-Once
  4. 再读 插件发现与类加载
  5. 最后结合 开发自己的 Connector