Flink 连接器与格式thin/uber 制品、打包策略与上线清单
一、为什么要关心“连接器与格式”?
- 连接器(Connector):让 Flink 读写外部系统(Kafka、Pulsar、S3/HDFS、JDBC、Elasticsearch…)。
- 格式(Format):在流与表之间进行数据编解码(JSON、CSV、Avro、Parquet、Debezium-JSON…)。
不同项目对依赖控制、部署方式、SQL Client 体验的诉求不同,因此需要在 thin vs uber 与 shade vs 分发到 /lib 之间做好权衡。
二、制品形态:thin vs uber(fat)
-
flink-connector-<NAME>
(thin JAR)- 只含连接器代码,不含第三方依赖。
- 适合需要精细控制传递依赖、避免与现有依赖冲突的场景。
-
flink-sql-connector-<NAME>
(uber/fat JAR)- 即开即用,已打包第三方依赖。
- 面向 SQL Client 使用场景;也可用于 DataStream/Table 应用。
注:有些连接器不需要第三方依赖,可能没有对应的
flink-sql-connector-<NAME>
。
三、集成方式:三条路线
(1)将 thin JAR 及其传递依赖 shade 进作业 JAR
- 优点:对传递依赖版本有最大掌控力;可在不改连接器版本的前提下替换底层依赖(需保持二进制兼容)。
- 适合:大型工程、复杂依赖树、与平台/老依赖共存。
(2)将 uber JAR 直接 shade 进作业 JAR
- 优点:最省事;拿来就用。
- 适合:快速交付、单体作业、PoC/演示环境。
(3)把 uber JAR 放进 Flink 发行版 /lib
目录
- 优点:集中在一处控制连接器版本,统一所有作业;集群层面变更更简单。
- 适合:平台化运维、同一集群多作业共享依赖。
四、选择建议(快速决策表)
诉求 | 推荐做法 |
---|---|
强依赖控制、避免冲突 | thin JAR + shade(含传递依赖) |
快速落地、少折腾 | uber JAR + shade |
多作业统一、平台管理 | uber JAR 放到 /lib |
主要用 SQL Client | uber JAR(优先) |
五、DataStream vs Table/SQL 的差异
-
DataStream:通常需要在应用构建阶段引入连接器与格式;自管依赖更常见。
-
Table/SQL:偏向声明式;
CREATE TABLE ... WITH ('connector'='kafka', ...)
即可使用。- 在 SQL Client 中使用连接器时,uber JAR 体验最佳(开箱即用)。
六、Maven/Gradle 打包示例
(一)Maven:thin JAR + 传递依赖(shade 到 uber 作业包)
<dependencies><!-- 连接器 thin JAR --><dependency><groupId>org.apache.flink</groupId><artifactId>flink-connector-kafka</artifactId><version>${flink.version}</version></dependency><!-- 格式(示例:JSON) --><dependency><groupId>org.apache.flink</groupId><artifactId>flink-json</artifactId><version>${flink.version}</version></dependency><!-- 由集群提供的运行时:provided,避免打包冲突 --><dependency><groupId>org.apache.flink</groupId><artifactId>flink-clients</artifactId><version>${flink.version}</version><scope>provided</scope></dependency>
</dependencies><build><plugins><plugin><groupId>org.apache.maven.plugins</groupId><artifactId>maven-shade-plugin</artifactId><version>3.5.1</version><executions><execution><phase>package</phase><goals><goal>shade</goal></goals><configuration><filters><filter><artifact>*:*</artifact><excludes><exclude>META-INF/*.SF</exclude><exclude>META-INF/*.DSA</exclude><exclude>META-INF/*.RSA</exclude></excludes></filter></filters><transformers><transformer implementation="org.apache.maven.plugins.shade.resource.ServicesResourceTransformer"/><transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer"><mainClass>org.example.MyJob</mainClass></transformer></transformers></configuration></execution></executions></plugin></plugins>
</build>
(二)Gradle Shadow:uber JAR 方案(最省事)
plugins {id 'java'id 'application'id 'com.github.johnrengelman.shadow' version '8.1.1'
}ext { flinkVersion = '2.1.0' }
repositories { mavenCentral() }dependencies {// 直接用 uber 版(SQL 体验更好):implementation "org.apache.flink:flink-sql-connector-kafka:${flinkVersion}"// 由集群提供的运行时(不要打包):compileOnly "org.apache.flink:flink-clients:${flinkVersion}"
}application { mainClass = 'org.example.MyJob' }tasks.shadowJar {archiveClassifier.set('all')mergeServiceFiles()exclude 'META-INF/*.SF', 'META-INF/*.DSA', 'META-INF/*.RSA'manifest { attributes 'Main-Class': 'org.example.MyJob' }
}
七、部署与运维模式
- 作业私有 JAR:每个作业自带全部所需依赖,独立性强;升级不影响其他作业。
- 集群共享
/lib
:集中管理版本;适合同构作业、大量 SQL 作业;需注意不同作业对版本的兼容性。
提交命令示例:
bin/flink run -c org.example.MyJob build/libs/my-job-1.0.0-all.jar
# 若 Manifest 已写 Main-Class,可省略 -c
# bin/flink run build/libs/my-job-1.0.0-all.jar
八、常见坑与排查
-
类冲突 / NoSuchMethodError / LinkageError
- 现象:运行时报错,或 SQL Client 启动失败。
- 原因:把
flink-clients
/flink-table-runtime
/planner-loader
等集群运行时打进了作业 JAR。 - 处置:将其标记为
provided/compileOnly
,仅 shade 连接器与第三方依赖。
-
SQL Client 识别不到连接器
- 原因:缺少 uber JAR 或未放入
/lib
。 - 处置:将
flink-sql-connector-<NAME>
放入 SQL Client 的 classpath(推荐/lib
)。
- 原因:缺少 uber JAR 或未放入
-
依赖版本“绑死”难以升级
- 现象:不同作业对某三方库版本诉求冲突。
- 策略:DataStream 更倾向 thin + shade;SQL 作业多则统一
/lib
。
-
Uber 与 Thin 混用踩坑
- 建议:同一连接器选一种路径(要么全项目用 thin+shade,要么统一
/lib
uber),减少定位复杂度。
- 建议:同一连接器选一种路径(要么全项目用 thin+shade,要么统一
九、性能与安全小贴士
- 依赖最小化:仅引入必要的格式与连接器;移除未用模块,减小 JAR,降低冷启动时延。
- 序列化选择:高吞吐推荐 Avro/Parquet(批/湖场景),JSON 便捷但 CPU 成本更高。
- 网络与 checkpoint:Kafka Source 建议启用 Exactly-Once(需事务 Sink 协同);关注 checkpoint 时长与 backpressure。
- 安全:shade 时排除
META-INF
签名文件;敏感凭据用环境变量/密钥管理,不要写死到配置里。
十、实践收尾:一套可复用的流程
(1)明确作业类型:DataStream(偏工程)还是 Table/SQL(偏声明式)。
(2)据此选择:thin+shade(可控)或 uber(省事)。
(3)制定团队规范:
- 运行时模块 provided/compileOnly;
- 连接器/格式 implementation 并 shadow;
- SQL Client 统一
/lib
。
(4)在 CI 中固化:依赖扫描、冲突检查(mvn dependency:tree
/gradle dependencies
)、产物验收(是否包含预期依赖)。
(5)灰度验证:测试集群回放流量,观察延迟、吞吐、checkpoint 指标与错误日志。