Description

一段简单的 FlinkSQL 程序,在 IDE 中运行没问题,但是 maven 打包后发布到终端启动却报错了。

import org.apache.flink.configuration.Configuration;
import org.apache.flink.streaming.api.environment.StreamExecutionEnvironment;
import org.apache.flink.table.api.StatementSet;
import org.apache.flink.table.api.bridge.java.StreamTableEnvironment; public class FlinkSQL { public static void main(String[] args) throws Exception {
Configuration configuration = new Configuration();
configuration.setInteger("rest.port", 9091);
StreamExecutionEnvironment env = StreamExecutionEnvironment.createLocalEnvironmentWithWebUI(configuration);
StreamTableEnvironment tableEnv = StreamTableEnvironment.create(env); String createSourceTableSQL = "CREATE TABLE source_dest (" +
"`id` INT," +
"`player` STRING," +
"`team` STRING," +
"`score` INT," +
"PRIMARY KEY (`id`) NOT ENFORCED" +
") WITH (" +
"'connector' = 'mysql-cdc'," +
"'hostname' = '10.4.45.207'," +
"'username' = 'username'," +
"'password' = 'password'," +
"'database-name' = 'cdc_test_source'," +
"'table-name' = 'player_scores'," +
"'scan.startup.mode' = 'latest-offset'" +
");";
tableEnv.executeSql(createSourceTableSQL); String createSinkTableSQL = "CREATE TABLE sink_dest (" +
"`id` INT," +
"`player` STRING," +
"`team` STRING," +
"`score` INT," +
"PRIMARY KEY (`id`) NOT ENFORCED" +
") WITH (" +
"'connector' = 'jdbc'," +
"'url' = 'jdbc:mysql://10.4.45.207:3306/cdc_test_target'," +
"'username' = 'username'," +
"'password' = 'password'," +
"'table-name' = 'player_scores'" +
");";
tableEnv.executeSql(createSinkTableSQL); String insertSQL = "INSERT INTO sink_dest SELECT * FROM source_dest;";
StatementSet statementSet = tableEnv.createStatementSet();
statementSet.addInsertSql(insertSQL);
statementSet.execute();
}
}

maven 的 pom.xml

<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>org.example</groupId>
<artifactId>flink-learning</artifactId>
<version>0.0.1-SNAPSHOT</version>
<description>flink</description> <properties>
<scala.binary.version>2.12</scala.binary.version>
<flink.version>1.15.4</flink.version>
</properties> <dependencies>
<dependency>
<groupId>org.apache.flink</groupId>
<artifactId>flink-java</artifactId>
<version>${flink.version}</version>
</dependency>
<dependency>
<groupId>org.apache.flink</groupId>
<artifactId>flink-runtime-web</artifactId>
<version>${flink.version}</version>
</dependency>
<dependency>
<groupId>org.apache.flink</groupId>
<artifactId>flink-table-api-java-bridge</artifactId>
<version>${flink.version}</version>
</dependency>
<dependency>
<groupId>org.apache.flink</groupId>
<artifactId>flink-table-runtime</artifactId>
<version>${flink.version}</version>
</dependency>
<dependency>
<groupId>org.apache.flink</groupId>
<artifactId>flink-table-planner-loader</artifactId>
<version>${flink.version}</version>
</dependency>
<dependency>
<groupId>org.apache.flink</groupId>
<artifactId>flink-connector-base</artifactId>
<version>${flink.version}</version>
</dependency>
<dependency>
<groupId>org.apache.flink</groupId>
<artifactId>flink-connector-jdbc</artifactId>
<version>${flink.version}</version>
</dependency>
<dependency>
<groupId>com.ververica</groupId>
<artifactId>flink-connector-mysql-cdc</artifactId>
<version>2.4.0</version>
</dependency>
</dependencies> <build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>3.1.1</version>
<configuration>
<createDependencyReducedPom>false</createDependencyReducedPom>
</configuration>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>shade</goal>
</goals>
<configuration>
<filters>
<filter>
<!-- Do not copy the signatures in the META-INF folder. Otherwise,
this might cause SecurityExceptions when using the JAR. -->
<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>org.example.test.FlinkSQL</mainClass>
</transformer>
</transformers>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>

使用 maven-shade-plugin 打包成 jar 后,直接使用 java -jar 命令启动,遇到报错:

Exception in thread "main" org.apache.flink.table.api.TableException: Could not instantiate the executor. Make sure a planner module is on the classpath
at org.apache.flink.table.api.bridge.internal.AbstractStreamTableEnvironmentImpl.lookupExecutor(AbstractStreamTableEnvironmentImpl.java:108)
at org.apache.flink.table.api.bridge.java.internal.StreamTableEnvironmentImpl.create(StreamTableEnvironmentImpl.java:100)
at org.apache.flink.table.api.bridge.java.StreamTableEnvironment.create(StreamTableEnvironment.java:122)
at org.apache.flink.table.api.bridge.java.StreamTableEnvironment.create(StreamTableEnvironment.java:94)
at org.example.test.FlinkSQL.main(FlinkSQL.java:19)
Caused by: org.apache.flink.table.api.ValidationException: Could not find any factories that implement 'org.apache.flink.table.delegation.ExecutorFactory' in the classpath.
at org.apache.flink.table.factories.FactoryUtil.discoverFactory(FactoryUtil.java:526)
at org.apache.flink.table.api.bridge.internal.AbstractStreamTableEnvironmentImpl.lookupExecutor(AbstractStreamTableEnvironmentImpl.java:105)
... 4 more

Locate

找不到 org.apache.flink.table.delegation.ExecutorFactory 的实现类?

跟踪源码查看一下:

step into 继续跟进

step into 继续跟进

到这里就很明确了,原来是找不到 SPI 的实现类。SPI 的加载路径是 META-INF/services, 打开 jar 包查看一下:

org.apache.flink.table.factories.Factory 中只有 3 个注册的 class, 其中确实没有 org.apache.flink.table.delegation.ExecutorFactory 的实现类。

IDE 中可以运行,打包后出现异常,说明是打包过程出现了问题。

排查后发现,项目中的依赖中存在不止一个 org.apache.flink.table.factories.Factory 的 SPI:

而使用 maven-shade-plugin 打包时,默认将第一个依赖 (flink-table-api-java-bridge.jar)中的 META-INF/services 打包进来,并忽略了其他依赖中存在的同名 SPI。

Fixed

我们希望将所有依赖中存在的同名 SPI 中的内容进行 merge,Flink 官方文档 给出了解决办法:

Flink uses Java's Service Provider Interfaces (SPI) to load the table connector/format factories by their identifiers. Since the SPI resource file named org.apache.flink.table.factories.Factory for every table connector/format is under the same directory META-INF/services, these resource files will override each other when build the uber-jar of the project which uses more than one table connector/format, which will cause Flink to fail to load table connector/format factories.

实际上只需要给 maven-shade-plugin 添加一项配置:

<!-- The service transformer is needed to merge META-INF/services files -->
<transformer implementation="org.apache.maven.plugins.shade.resource.ServicesResourceTransformer">
</transformer>

重新打包,验证一下:

重新启动程序:

java -jar flink-learning-0.0.1-SNAPSHOT.jar

运行成功:

【Flink 日常踩坑】Could not find ExecutorFactory in classpath的更多相关文章

  1. 日常踩坑 — 相邻元素之间的margin合并问题。

    踩坑:使用v-for渲染的组件,当然图中的id已经换成class,还是没有解决这个问题,于是各种查找资料,我就不信简单的CSS问题这么难解决! v-for渲染组件级传值: <div class= ...

  2. 日常踩坑 searter

    目录 es7中的async, await Django生成二维码并转为base64 Django配置404页面 很傻逼的坑 no module named pil 其他 es7中的async, awa ...

  3. 日常踩坑——Dev C++ pow()函数的坑

    坑 Dev C++ pow()函数 那年冬天,显示屏前坐着如喽啰,那时候我含泪发誓,再也不用Dev. 蓝桥杯官网给提供的版本,没办法bug也得硬着头皮用. 16年蓝桥杯的第八题 四平方和定理: 在De ...

  4. 日常踩坑-------新手使用idea

    mybatis在idea的maven项目中的坑 今天遇到mybatis的报错,搞了好久才搞懂,在网上找了好久的相似案例,也没有搞定,先来看下网上常见的解决办法吧,相信也能解决大部分人的报错. 1.ma ...

  5. 日常踩坑笔记:spring的context:property-placeholder标签

    背景: 原来的项目一直跑着没有问题,今天突然想在原有项目的基础上,加上redis进行数据的缓存,原来项目的架构就是传统的SSM框架,于是,大刀阔斧的开始改装了... 编写redis的配置文件——red ...

  6. 日常踩坑——rand()总是出现重复数据

    写了一个生成随机数组的函数,然后跑出来,结果总是…… 然后,很奇怪的是一步一步调试,它就没问题了,WTF??? 问题出在:重复写了srand(time(NULL)),只保留一个就好了. int* ge ...

  7. 【React Native】日常踩坑记录_以后将持续更新

    作为一名有理想.有抱负的一代iOS程序员,本着“我头发够多,还能学”的原则,我选择了追随那些大佬的脚步,于2018年开始了React Native. 第一步:找文档.准备安装开发环境: 第二步:一步步 ...

  8. 『vue踩坑日常』 在index.html中引入静态文件不生效

    Vue日常踩坑日常 -- 在index.html中引入静态文件不生效问题 本文针对的是Vue小白,不喜勿喷,谢谢 出现该问题的标志如下 控制台warning(Resource interpreted ...

  9. Vue packages version mismatch的解决方法 初来乍到,踩坑日常

    初来乍到,踩坑日常 这个问题也是我也是接受别人项目,出现的问题,在下载好依赖后运行的时候报这样的错误 它上面显示两个版本一个vue的版本,一个vue-template-compiler版本,我这边忘了 ...

  10. Java 开发中如何正确踩坑

    为什么说一个好的员工能顶 100 个普通员工 我们的做法是,要用最好的人.我一直都认为研发本身是很有创造性的,如果人不放松,或不够聪明,都很难做得好.你要找到最好的人,一个好的工程师不是顶10个,是顶 ...

随机推荐

  1. SAR靶机笔记

    SAR 靶机笔记 概述 SAR 是 Vulnhub 上的靶机,大家可以去 vulnhub 网站上去进行下载. 这里有链接: https://download.vulnhub.com/sar/sar.z ...

  2. 【图文安装教程】在docker中安装ES

    在docker中安装ES怎么安装?本文就教大家怎么安装 1.部署单点es 1.1.创建网络 因为我们还需要部署kibana容器,因此需要让es和kibana容器互联.这里先创建一个网络: docker ...

  3. 安全 – 常见 Web 攻击

    前言 最近在研究 WAF, 顺便记入一下常见的 Web 攻击. SQL Injection SQL injection 是指程序员直接拿 client input, 拼接到 SQL query 中. ...

  4. ASP.NET Core – MVC vs Razor Page

    前言 早年只有 MVC, Razor Page 是后来才出现的. 一开始其实我很看不起 Razor Page, MVC 能做的东西为什么要搞多一个 Razor Page 来做呢? 但我还是尝试用了起来 ...

  5. 【VMware VCF】使用 VCF Import Tool 将现有 vSphere 环境转换为管理域。

    VMware Cloud Foundation 5.2 发布并引入了一个新的功能,借助 VCF Import Tool 工具可以将现有 vSphere 环境直接转换(Convert)为管理工作负载域或 ...

  6. Session——基本使用

    Session    Session 原理 Session 使用细节      

  7. MVC模式与三层架构

    MVC 模式    三层架构    MVC 模式 与 三层架构 的关系   

  8. K8S命名空间处于Terminating状态,如何强制删除

    一.现象 当删除命名空间后,发现该空间一直处于Terminating状态 [root@imanager-beta-arm-21756-5g5ap ~]# kubectl get ns NAME STA ...

  9. 浅谈数栈产品里的 Descriptions 组件

    我们是袋鼠云数栈 UED 团队,致力于打造优秀的一站式数据中台产品.我们始终保持工匠精神,探索前端道路,为社区积累并传播经验价值. 本文作者:修能 What's? 数栈产品里的 Description ...

  10. spring 拦截器实现token校验登录

    pom文件 <dependency> <groupId>com.auth0</groupId> <artifactId>java-jwt</art ...