Flink+StateFun+SpringBoot提交集群报ProgramInvocationException
- 依赖冲突:打包fat jar时未将Flink核心依赖、Stateful Functions核心依赖设置为
provided级别,集群内置的依赖和jar包内重复引入的依赖版本不匹配,触发类加载异常,最终抛出ProgramInvocationException。 - 打包结构不兼容:使用Spring Boot默认repackage逻辑生成的fat jar采用
BOOT-INF嵌套目录结构,Flink与Stateful Functions的类加载器默认无法扫描该嵌套路径下的自定义函数实现、SPI配置文件,作业初始化阶段就会失败。 - SPI配置缺失:未按Stateful Functions的加载规则,在
META-INF/services路径下配置模块声明文件,启动时无法识别自定义的有状态函数逻辑。
1. 调整依赖作用域
在构建配置(Maven/Gradle)中,将所有Flink、Stateful Functions核心依赖的作用域设置为provided,这类依赖由Flink Standalone集群运行时统一提供,无需打入业务jar包,避免版本冲突。
Maven配置示例:
<dependency> <groupId>org.apache.flink</groupId> <artifactId>flink-java</artifactId> <version>${flink.version}</version> <scope>provided</scope> </dependency> <dependency> <groupId>org.apache.flink</groupId> <artifactId>statefun-sdk</artifactId> <version>${statefun.version}</version> <scope>provided</scope> </dependency> <dependency> <groupId>org.apache.flink</groupId> <artifactId>statefun-flink-core</artifactId> <version>${statefun.version}</version> <scope>provided</scope> </dependency>
注意:Spring Boot自带的工具类、web等轻量依赖如果集群未内置,可以正常打入jar包,无需设置为provided。
2. 修正打包配置
不要直接提交Spring Boot默认repackage生成的嵌套结构jar包,改用maven-shade-plugin打Flink兼容的扁平结构fat jar,同时配置服务资源转换器合并SPI配置,避免配置被覆盖。
插件配置示例:
<plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-shade-plugin</artifactId> <version>3.4.1</version> <executions> <execution> <phase>package</phase> <goals> <goal>shade</goal> </goals> <configuration> <transformers> <!-- 合并所有META-INF/services下的SPI配置 --> <transformer implementation="org.apache.maven.plugins.shade.resource.ServicesResourceTransformer"/> <!-- 指定作业主类 --> <transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer"> <mainClass>org.apache.flink.statefun.flink.core.StatefulFunctionsJob</mainClass> </transformer> </transformers> <filters> <filter> <artifact>*:*</artifact> <excludes> <!-- 排除签名文件避免类校验失败 --> <exclude>META-INF/*.SF</exclude> <exclude>META-INF/*.DSA</exclude> <exclude>META-INF/*.RSA</exclude> </excludes> </filter> </filters> </configuration> </execution> </executions> </plugin>
如果需要保留Spring Boot本地可执行能力,可以单独配置spring-boot-maven-plugin的classifier,区分本地启动包和Flink提交包,避免混淆。
3. 补全StateFun SPI配置
在项目资源目录下创建META-INF/services/org.apache.flink.statefun.sdk.spi.StatefulFunctionModule文件,文件内容填写自定义StateFun模块类的全限定名,示例:
com.example.statefun.GreetingModule
需要确保模块类中正确绑定了问候函数的实现、对应的ingress/egress路由规则。
4. 作业提交验证
重新打包后,可直接执行提交命令,shade插件已经在jar包MANIFEST中声明了主类,无需额外通过-c指定:
./flink run ./statefun-example-1.0-SNAPSHOT.jar
如果仍需手动指定主类,先确认引入的StateFun版本对应的入口类全限定名,不同大版本的入口类路径可能存在差异。
内容的提问来源于stack exchange,提问作者Rams

