用 Gradle 配置 Flink 从开发到打包的一条龙实践

一、环境要求与项目初始化

  • Gradle:7.x
  • Java:11(支持 8,但已不推荐)

提示:若你使用 Gradle Wrapper,命令均可替换为 ./gradlew ...,避免本机 Gradle 版本不一致。

二、IDE 导入与本地运行

  • IntelliJ IDEA:原生 Gradle 插件即可。

    • 运行配置里勾选 Include dependencies with "Provided" scope (旧版没有该选项时,可写一个测试用例调用 main() 代跑)。
    • JVM 堆内存:Help -> Edit Custom VM Options,增加如 -Xmx800m
  • Eclipse :使用 Eclipse Buildship 插件(导入向导最后一步确保 Gradle 版本 ≥ 3.0,Shadow 插件需要)。

三、项目结构与主类配置

  • 默认示例主类通常叫 StreamingJob(可能因模板而异)。

  • 若主类不同,建议在 build.gradle 中设置:

    groovy 复制代码
    application {
      mainClass = 'org.example.MyJob'   // Gradle 7 推荐写法
    }

    或在 shadowJar 的 Manifest 中指定主类(见第六节)。

这样打包后的 JAR 直接被 Flink 识别,无需每次提交都 -c org.example.MyJob

四、依赖管理:providedcompile 的边界

核心原则:

  • Flink 核心/运行时 (例如 flink-clientsflink-table-runtimeflink-table-planner-loader由集群提供 → 在工程中标记为 provided/compileOnly不要打进 JAR。
  • 你必须随作业分发 的依赖(连接器、格式库、业务 SDK)→ 设为 compile/runtime ,并通过 Shadow 打包进 fat/uber JAR。

示例(build.gradle

groovy 复制代码
plugins {
  id 'java'
  id 'application'
  id 'com.github.johnrengelman.shadow' version '8.1.1'
}

ext {
  flinkVersion = '2.1.0'
}

repositories { mavenCentral() }

dependencies {
  // 1) API(按需)
  implementation "org.apache.flink:flink-streaming-java:${flinkVersion}"
  implementation "org.apache.flink:flink-table-api-java:${flinkVersion}"
  implementation "org.apache.flink:flink-table-api-java-bridge:${flinkVersion}"

  // 2) 连接器/格式(打进 fat JAR)
  implementation "org.apache.flink:flink-connector-kafka:${flinkVersion}"
  implementation "org.apache.flink:flink-json:${flinkVersion}"

  // 3) 集群提供的运行时(不要打包)
  compileOnly "org.apache.flink:flink-clients:${flinkVersion}"
  compileOnly "org.apache.flink:flink-table-runtime:${flinkVersion}"
  compileOnly "org.apache.flink:flink-table-planner-loader:${flinkVersion}"

  // 4) 测试
  testImplementation "org.apache.flink:flink-test-utils-junit:${flinkVersion}"
  testImplementation "org.junit.jupiter:junit-jupiter:5.10.2"
}

application {
  mainClass = 'org.example.MyJob'
}

tasks.withType(Test).configureEach {
  useJUnitPlatform()
}

五、添加依赖的常见场景

Kafka Connector 为例(shadow 专用的配置法在很多模板中叫 flinkShadowJar;若无该自定义配置,implementation 即可):

groovy 复制代码
dependencies {
  // 如果模板定义了 'flinkShadowJar' 以便区分要打进 fat JAR 的依赖
  flinkShadowJar "org.apache.flink:flink-connector-kafka:${flinkVersion}"

  // 若没有该自定义配置,使用 implementation 也能被 Shadow 打入
  // implementation "org.apache.flink:flink-connector-kafka:${flinkVersion}"
}

关键不是名字,而是这些依赖最终会进入 Shadow 产物;而 Flink 核心运行时 保持 compileOnly/provided

六、打包策略:普通分发 vs fat/uber JAR

命令一览:

  • 本地快速打包 fat JAR(常用):

    bash 复制代码
    gradle clean shadowJar

    产物:build/libs/<project>-<version>-all.jar

  • 安装可分发目录(不含第三方 fat 合并)

    bash 复制代码
    gradle clean installDist

    适合"只依赖 Flink 发行版内置组件"的简单作业(例如 filesystem + JSON)。

  • 安装 fat 分发目录(单 JAR 带齐第三方依赖)

    bash 复制代码
    gradle clean installShadowDist

    产物在:build/install/<project>/lib/(包含单一 fat JAR)。

Shadow 细节(可选优化)

groovy 复制代码
tasks.shadowJar {
  archiveClassifier.set('all')
  mergeServiceFiles()
  exclude 'META-INF/*.SF', 'META-INF/*.DSA', 'META-INF/*.RSA' // 避免签名冲突
  manifest {
    attributes 'Main-Class': 'org.example.MyJob' // 双保险:Manifest 写主类
  }
}

建议:生产环境用 fat/uber JAR 更省心:一次打包,处处可跑;但务必别把 Flink 运行时也打进去。

七、提交运行与命令示例

bash 复制代码
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

亦可在 Kubernetes Application/Session 模式下提交,上线前先在测试集群验证。

八、常见问题与排查清单

(1)JAR 过大或类冲突

  • 症状:依赖冲突、NoSuchMethodErrorLinkageError
  • 原因:把 flink-clients/table-runtime/planner-loader 这类运行时打进了 fat JAR。
  • 解决:改为 compileOnly/provided,重新打包;核对依赖树(gradle dependencies)。

(2)IDE 能跑,集群报错

  • 原因:集群的 Flink 版本与本地依赖不匹配,或缺少对应运行时。
  • 解决:统一版本;确保运行时由集群提供,应用仅携带连接器与三方库。

(3)主类找不到

  • 原因:打包未写 Main-Class,或改了主类却没同步到配置。
  • 解决:application { mainClass = ... } 或在 shadowJar.manifest 写入。

(4)内存不足

  • 现象:IDE 或本地运行时 OOM。
  • 处理:增加 JVM 堆(-Xmx800m 起步),或在运行配置调大。

(5)Kafka/格式类找不到

  • 原因:连接器/格式库没有被 Shadow 打进产物。
  • 解决:确认依赖在 implementation 或模板的 flinkShadowJar;重新打包 shadowJar

九、实践建议与下一步

(1)以 Kafka → 清洗 → Sink 的最小链路为骨架,先在本地跑通。

(2)用 shadowJar 生成 fat JAR,在测试集群验证端到端。

(3)在 CI/CD 中固化:Gradle Wrapper + 版本锁定 + 产物归档 + 自动提交

(4)连接器与 Flink 版本强一致 ;显式设置有状态算子的 UID(与部署相关,但同样建议固定)。

依赖作用域 划清、把 Shadow 打包 配好、把 主类 写明白,你的 Flink + Gradle 项目就能稳定地在"开发---构建---部署"全链路运行。祝你第一条 Flink 作业流水线顺利上线!

相关推荐
赵部长风向标2 小时前
在本地生活赛道,如何打造属于自己的业务护城河?
大数据
青云交2 小时前
Java 大视界 -- Java 大数据在智能教育学习社区互动模式创新与用户活跃度提升中的应用(426)
java·大数据·学习·flink 实时计算·智能教育社区·互动模式创新·用户活跃度
snowful world5 小时前
flink实验三:实时数据流处理(踩坑记录)
大数据·flink
B站_计算机毕业设计之家5 小时前
基于大数据的短视频数据分析系统 Spark哔哩哔哩视频数据分析可视化系统 Hadoop大数据技术 情感分析 舆情分析 爬虫 推荐系统 协同过滤推荐算法 ✅
大数据·hadoop·爬虫·spark·音视频·短视频·1024程序员节
面向星辰6 小时前
day07 spark sql
大数据·sql·spark
北邮-吴怀玉7 小时前
2.2.2.3 大数据方法论与实践指南-开源服务跟踪工具对比
大数据·开源
亚远景aspice8 小时前
亚远景热烈祝贺保隆科技通过ASPICE CL2评估
大数据·人工智能·物联网
赵谨言9 小时前
基于python大数据的城市扬尘数宇化监控系统的设计与开发
大数据·开发语言·经验分享·python
程序员小羊!9 小时前
Flink状态编程之算子状态(OperatorState)
大数据·flink
TaoSense10 小时前
Milvus向量数据库介绍
大数据·人工智能