用 Maven 配置 Flink 从初始化到可部署的完整实践

一、环境与初始化

要求:

  • Maven ≥ 3.8.6
  • Java 11

初始化方式:

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

二、将项目导入 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-clientsflink-table-runtimeflink-table-planner-loader
    集群 中已有,应设为 provided (只编译,不打进 JAR)------避免 JAR 过大版本冲突
  • 必须随 JAR 分发的依赖 (连接器、格式库、三方 SDK)
    设为 compile ,并用 Shade 打进 uber/fat JAR。

一句话记忆:能让集群提供的就 provided;必须带去运行现场的就 compile + shade。

四、典型 pom.xml 片段

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>

五、构建与入口类

打包命令:

bash 复制代码
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
    (二)Shadeuber/fat JAR(推荐,分发更简单)。

提交示例:

bash 复制代码
bin/flink run -c org.example.MyJob myFatJar.jar

七、Maven Shade 插件模板(可直接粘贴)

xml 复制代码
<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 默认会打包 compileruntime 作用域依赖;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 作业上线顺利!

相关推荐
java_logo3 小时前
使用 Docker 部署 Nginx 教程
java·spring cloud·eureka
小蒜学长3 小时前
springboot基于BS的小区家政服务预约平台(代码+数据库+LW)
java·数据库·spring boot·后端
我命由我123453 小时前
Git 暂存文件警告信息:warning: LF will be replaced by CRLF in XXX.java.
java·linux·笔记·git·后端·学习·java-ee
小胖同学~3 小时前
JVM内存模型剖析
java·jvm
简色4 小时前
预约优化方案全链路优化实践
java·spring boot·后端·mysql·spring·rabbitmq
nice_lcj5204 小时前
深入理解ArrayList与LinkedList:Java集合框架核心对比(含实战案例+面试考点)
java·面试
小蕾Java4 小时前
IDEA快速上手指南!
java·intellij-idea·swift
聪明的笨猪猪4 小时前
Java 内存模型(JMM)面试清单(含超通俗生活案例与深度理解)
java·经验分享·笔记·面试
羚羊角uou4 小时前
【Linux】线程的互斥
java·开发语言