用 Maven 配置 Flink 从初始化到可部署的完整实践
一、环境与初始化
要求:
- Maven ≥ 3.8.6
- Java 11
初始化方式:
# 方式一:Archetype(交互式填写 groupId/artifactId/package)
mvn archetype:generate \-DarchetypeGroupId=org.apache.flink \-DarchetypeArtifactId=flink-quickstart-java \-DarchetypeVersion=2.1.0# 方式二:一键脚本
curl https://flink.apache.org/q/quickstart.sh | bash -s 2.1.0
二、将项目导入 IDE 并能“跑起来”
- IntelliJ IDEA:原生支持 Maven 项目;在 Run/Debug Configurations 勾选
Include dependencies with “Provided” scope(旧版无此选项时,可写一个测试用例调用main()
作为变通)。 - Eclipse:安装 m2e 插件导入 Maven 项目。
JVM 堆内存:默认堆可能偏小。
- Eclipse:
Run Configurations -> Arguments -> VM Arguments
添加:-Xmx800m
- IntelliJ:
Help -> Edit Custom VM Options
调整。
三、依赖管理的“黄金法则”
一个 Flink 作业通常需要三类依赖:
(1)Flink API(DataStream、Table/SQL 等)
(2)连接器/格式(Kafka、Filesystem、JSON/Avro 等)
(3)测试工具(例如 JUnit 与 Flink test utils)
(一)常见 API 依赖选择
- DataStream:
flink-streaming-java
- Table(Java):
flink-table-api-java
- Table + DataStream(Java 桥):
flink-table-api-java-bridge
(Scala 版本请使用_2.12
对应构件)
(二)“provided” 与 “compile” 怎么选?
- Flink 核心/运行时模块(如
flink-clients
、flink-table-runtime
、flink-table-planner-loader
)
在集群中已有,应设为provided
(只编译,不打进 JAR)——避免 JAR 过大 和 版本冲突。 - 必须随 JAR 分发的依赖(连接器、格式库、三方 SDK)
设为compile
,并用 Shade 打进 uber/fat JAR。
一句话记忆:能让集群提供的就 provided;必须带去运行现场的就 compile + shade。
四、典型 pom.xml
片段
<properties><maven.compiler.source>11</maven.compiler.source><maven.compiler.target>11</maven.compiler.target><flink.version>2.1.0</flink.version>
</properties><dependencies><!-- (一)APIs(按需添加) --><dependency><groupId>org.apache.flink</groupId><artifactId>flink-streaming-java</artifactId><version>${flink.version}</version></dependency><dependency><groupId>org.apache.flink</groupId><artifactId>flink-table-api-java</artifactId><version>${flink.version}</version></dependency><dependency><groupId>org.apache.flink</groupId><artifactId>flink-table-api-java-bridge</artifactId><version>${flink.version}</version></dependency><!-- (二)连接器/格式(随 JAR 分发,compile) --><dependency><groupId>org.apache.flink</groupId><artifactId>flink-connector-kafka</artifactId><version>${flink.version}</version></dependency><!-- (三)本地运行 main 需要,但集群会提供:设为 provided --><dependency><groupId>org.apache.flink</groupId><artifactId>flink-clients</artifactId><version>${flink.version}</version><scope>provided</scope></dependency><dependency><groupId>org.apache.flink</groupId><artifactId>flink-table-runtime</artifactId><version>${flink.version}</version><scope>provided</scope></dependency><dependency><groupId>org.apache.flink</groupId><artifactId>flink-table-planner-loader</artifactId><version>${flink.version}</version><scope>provided</scope></dependency><!-- (四)测试 --><dependency><groupId>org.apache.flink</groupId><artifactId>flink-test-utils-junit</artifactId><version>${flink.version}</version><scope>test</scope></dependency><dependency><groupId>org.junit.jupiter</groupId><artifactId>junit-jupiter</artifactId><version>5.10.2</version><scope>test</scope></dependency>
</dependencies>
五、构建与入口类
打包命令:
mvn clean package
产物位于 target/<artifact-id>-<version>.jar
。
入口类(mainClass):若主类不是默认 DataStreamJob
,请在 pom.xml
的打包配置(或 Shade 的 ManifestResourceTransformer
)里设置 mainClass
,提交 JAR 时就无需再手动 -c
指定。
六、何时需要 uber/fat JAR?
- 仅用 Flink 自带能力(如 filesystem + JSON) → 不需要 uber JAR,可直接提交普通 JAR。
- 引入外部依赖/连接器(发行版未内置) →
(一)把依赖放进集群 classpath;
(二)Shade 成 uber/fat JAR(推荐,分发更简单)。
提交示例:
bin/flink run -c org.example.MyJob myFatJar.jar
七、Maven Shade 插件模板(可直接粘贴)
<build><plugins><plugin><groupId>org.apache.maven.plugins</groupId><artifactId>maven-shade-plugin</artifactId><version>3.1.1</version><executions><execution><phase>package</phase><goals><goal>shade</goal></goals><configuration><artifactSet><excludes><exclude>com.google.code.findbugs:jsr305</exclude></excludes></artifactSet><filters><filter><!-- 不拷贝签名,避免 SecurityException --><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.ManifestResourceTransformer"><mainClass>my.programs.main.clazz</mainClass></transformer><transformer implementation="org.apache.maven.plugins.shade.resource.ServicesResourceTransformer"/></transformers></configuration></execution></executions></plugin></plugins>
</build>
Shade 默认会打包
compile
与runtime
作用域依赖;provided
不会被打进 JAR。
八、实用小贴士与常见坑
小贴士
(1)IntelliJ 运行作业:勾选 Include dependencies with “Provided” scope,否则本地跑可能找不到 Flink 运行时类。
(2)连接器版本与 Flink 版本对齐,避免 classpath 冲突。
(3)固定入口类:减少提交参数,降低运维摩擦。
常见坑
(1)JAR 体积巨大或冲突:把 flink-clients/table-runtime/planner-loader
打进了 JAR → 改成 provided
。
(2)NoSuchMethodError / ClassNotFound:连接器没被 shade 进来或版本不匹配 → 查 dependency:tree
并调整。
(3)IDE 能跑,集群失败:集群侧缺少匹配版本运行时模块 → 对齐集群与本地依赖。
(4)老 IntelliJ 无 provided 选项:用测试用例调用 main()
代跑。
(5)主类不对导致提交失败:pom.xml
未配置 mainClass
或写错 → 在 Shade Manifest 中显式指定。
九、你的下一步
(1)挑一个最小作业(Kafka → 清洗 → Sink),补齐 API + 连接器 依赖。
(2)用 Shade 打出一个 uber JAR,在本地与测试集群各跑一遍。
(3)把打包与提交接入 CI/CD(构建、制品库、部署到 Session/Application Cluster)。
把依赖作用域分得清、Shade 配置写得对、入口类设得明白,你的 Flink 项目就能顺滑地在本地开发、CI 构建与集群部署之间切换。祝你首个 Maven 驱动的 Flink 作业上线顺利!