Flink 项目配置从 0 到可部署

一、快速起步:用官方骨架拉起项目

Maven:Archetype 或 quickstart 脚本(二选一)

bash 复制代码
# 方式一: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

上述命令会生成一套最小可运行骨架;之后你只需要补齐依赖与打包配置。

Gradle

Gradle 没有官方一键脚本也没关系,直接新建工程并按下文添加依赖与 shadow 配置即可。

二、到底需要哪些依赖?

一个可用的 Flink 作业通常包含 3 类依赖:

  1. Flink APIs(编写作业逻辑必需)
  2. 连接器 / 格式(接入 Kafka/Cassandra/文件/JSON/Avro 等)
  3. 测试工具(本地/集成测试)

此外,你还会按需添加三方库(比如 Jackson、Guava、业务 SDK),用于 UDF/序列化/自定义逻辑。

你要用的 API 需要添加
DataStream flink-streaming-java
Table API(Java) flink-table-api-java
Table API(Scala) flink-table-api-scala_2.12
Table + DataStream(Java 桥) flink-table-api-java-bridge
Table + DataStream(Scala 桥) flink-table-api-scala-bridge_2.12

混用场景(既要 Table 也要 DataStream)记得加 bridge

2.2 运行所需的"客户端/运行时"模块

  • 直接本地跑 main :需要 flink-clientsclasspath 中。
  • Table 程序 :还需要 flink-table-runtimeflink-table-planner-loader

注意:这些模块通常由 Flink 集群提供打包 uber JAR 时不要把它们塞进去(后文有配置)。

三、Maven 版:依赖与打包最佳实践

3.1 pom.xml 依赖示例(精简版)

xml 复制代码
<properties>
  <java.version>17</java.version>
  <flink.version>2.1.0</flink.version>
  <scala.binary.version>2.12</scala.binary.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>

  <!-- 连接器/格式(示例:Kafka + JSON) -->
  <dependency>
    <groupId>org.apache.flink</groupId>
    <artifactId>flink-connector-kafka</artifactId>
    <version>${flink.version}</version>
  </dependency>
  <dependency>
    <groupId>org.apache.flink</groupId>
    <artifactId>flink-json</artifactId>
    <version>${flink.version}</version>
  </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>

  <!-- 本地运行 main 需要(集群环境下建议 provided) -->
  <dependency>
    <groupId>org.apache.flink</groupId>
    <artifactId>flink-clients</artifactId>
    <version>${flink.version}</version>
    <scope>provided</scope>
  </dependency>
  <!-- Table 程序运行时(集群提供,uber JAR 不要打入) -->
  <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>
</dependencies>

3.2 Maven Shade:只打"你必须带的"

目标 :把你的应用代码 + 连接器/格式 + 三方库 打进 uber JAR;不要把集群已提供的 Flink 运行时重复打包(避免冲突与超大 JAR)。

xml 复制代码
<build>
  <plugins>
    <!-- Java 版本 & 编译插件略 -->
    <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>
            <createDependencyReducedPom>true</createDependencyReducedPom>
            <filters>
              <!-- 忽略签名元数据:防止合并冲突 -->
              <filter>
                <artifact>*:*</artifact>
                <excludes>
                  <exclude>META-INF/*.SF</exclude>
                  <exclude>META-INF/*.DSA</exclude>
                  <exclude>META-INF/*.RSA</exclude>
                </excludes>
              </filter>
            </filters>
            <!-- 避免把 flink-clients/table-runtime/planner-loader 等 provided 进来 -->
            <artifactSet>
              <excludes>
                <exclude>org.apache.flink:flink-clients</exclude>
                <exclude>org.apache.flink:flink-table-runtime</exclude>
                <exclude>org.apache.flink:flink-table-planner-loader</exclude>
              </excludes>
            </artifactSet>
            <!-- 可选:合并 SPI(例如 Kafka 序列化 SPI) -->
            <transformers>
              <transformer implementation="org.apache.maven.plugins.shade.resource.ServicesResourceTransformer"/>
              <transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
                <mainClass>com.example.YourMainClass</mainClass>
              </transformer>
            </transformers>
          </configuration>
        </execution>
      </executions>
    </plugin>
  </plugins>
</build>

打包完成后得到一个 可提交的 job JAR:既包含连接器与三方依赖,又不会和集群里的 Flink 运行时"打架"。

四、Gradle 版:依赖与 Shadow 打包

4.1 build.gradle(Groovy)示例

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

ext {
  flinkVersion = '2.1.0'
  scalaBinary = '2.12'
}

repositories { mavenCentral() }

dependencies {
  // APIs
  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}"

  // 连接器/格式
  implementation "org.apache.flink:flink-connector-kafka:${flinkVersion}"
  implementation "org.apache.flink:flink-json:${flinkVersion}"

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

  // 集群提供的运行时(标记为 compileOnly / runtimeOnly)
  compileOnly "org.apache.flink:flink-clients:${flinkVersion}"
  compileOnly "org.apache.flink:flink-table-runtime:${flinkVersion}"
  compileOnly "org.apache.flink:flink-table-planner-loader:${flinkVersion}"
}

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

jar {
  manifest {
    attributes 'Main-Class': 'com.example.YourMainClass'
  }
}

tasks.shadowJar {
  archiveClassifier.set('all')
  // 典型冲突处理
  mergeServiceFiles()
  exclude 'META-INF/*.SF', 'META-INF/*.DSA', 'META-INF/*.RSA'
}

产物为 your-artifact-all.jar(即 uber JAR),提交到集群即可运行。

五、运行与提交:本地调试 vs 集群提交

本地调试

  • 直接运行 main(IDE/CLI),确保 flink-clients 在 classpath。
  • Table 程序本地跑需 flink-table-runtimeflink-table-planner-loader

集群提交(Session / Application)

bash 复制代码
# 提交到已运行的 Session Cluster
flink run -c com.example.YourMainClass /path/to/your-app-all.jar

# Kubernetes Application 模式(示意)
flink run-application \
  -t kubernetes-application \
  -Dkubernetes.cluster-id=my-flink-app \
  -Dtaskmanager.numberOfTaskSlots=2 \
  local:///opt/flink/usrlib/your-app-all.jar

六、测试与本地验证(建议)

  • 单元测试flink-test-utils-junit + JUnit 5,对 UDF/函数逻辑做纯逻辑测试。
  • 集成测试 :本地启动 mini-cluster(MiniClusterWithClientResource)或 Testcontainers + Kafka,验证端到端拓扑。
  • Schema/格式测试:给 JSON/Avro/CSV 读写器构造"好/坏样例",避免线上解析炸裂。

七、上线自检清单(Do/Don't)

Do

  • uber JAR 打包你的代码、连接器与三方库。
  • flink-clients / flink-table-runtime / flink-table-planner-loader 设为 provided/compileOnly(由集群提供)。
  • Table + DataStream 混用时记得添加 bridge 依赖
  • 统一 Flink 版本连接器版本(以 Flink 为准),避免 classpath 冲突。
  • 为有状态算子设置 稳定的 UID,保障 savepoint 恢复。

Don't

  • 不要把 Flink 发行版里的核心运行时打进 uber JAR(体积暴涨 + 冲突)。
  • 不要混用不兼容的 Scala 二进制版本_2.11/_2.12 不能乱配)。
  • 不要在多个模块里各自 shade 同一大依赖(尽量在最上层汇总)。

八、常见坑与快速排查

  • 提交时报类冲突 / NoSuchMethodError
    → 检查是否把 flink-table-runtime/planner-loader 打进了 uber JAR;核对依赖树(mvn dependency:tree / gradle dependencies)。
  • Table 程序本地能跑,集群失败
    → 集群端是否有匹配版本的 table-runtime/planner-loader;Planner Loader 未对得上。
  • Kafka 连接器运行时报找不到类
    → 没有把 flink-connector-kafka 打进 uber JAR;或版本与 Flink 不匹配。
  • Scala 相关报错
    → 统一 _2.12,避免把 _2.11 依赖带进来。
  • JAR 超大/冷启动慢
    → 排查是否误打入 Flink 自带模块;尽量移除冗余依赖与签名元数据。
相关推荐
安达发公司9 分钟前
安达发|告别手工排产!车间排产软件成为中央厨房的“最强大脑”
大数据·人工智能·aps高级排程·aps排程软件·安达发aps·车间排产软件
武子康41 分钟前
大数据-166 Apache Kylin 1.6 Streaming Cubing 实战:Kafka 到分钟级 OLAP
大数据·后端·apache kylin
啊吧怪不啊吧1 小时前
SQL之表的字符串内置函数详解
大数据·数据库·sql
亿坊电商1 小时前
24H-无人共享KTV:如何实现安全的自助服务?
大数据·物联网·安全
草莓熊Lotso4 小时前
Git 分支管理:从基础操作到协作流程(本地篇)
大数据·服务器·开发语言·c++·人工智能·git·sql
Bug快跑-15 小时前
面向高并发场景的多语言异构系统架构演进与性能优化策略深度解析实践分享全过程方法论探索
flink
GIS数据转换器15 小时前
GIS+大模型助力安全风险精细化管理
大数据·网络·人工智能·安全·无人机
hg011815 小时前
今年前10个月天津进出口总值6940.2亿元
大数据
byte轻骑兵16 小时前
时序数据库选型指南:从大数据视角看IoTDB的核心优势
大数据·时序数据库·iotdb
Leo.yuan17 小时前
制造业都在说BOM,为什么BOM这么重要?
大数据·bom·企业数字化·数字赋能