在flink写doris时报了个错。查网上的资料,不止sink doris会出现这个问题,sink kafka,
其实同样的程序在一个电脑上成功过,所以说明依赖是没有问题的。但是换了个电脑打包就失败了
Caused by: org.apache.flink.table.api.ValidationException: Could not find any factory for identifier 'doris' that implements 'org.apache.flink.table.factories.DynamicTableFactory' in the classpath.
Available factory identifiers are:
blackhole
datagen
filesystem
iceberg
pegasus
print
talos
at org.apache.flink.table.factories.FactoryUtil.discoverFactory(FactoryUtil.java:235)
at org.apache.flink.table.factories.FactoryUtil.enrichNoMatchingConnectorError(FactoryUtil.java:363)
问题分析
工程本地运行正常,打包提交flink时报缺少依赖,分析问题可能出在打包。查看打包日志,打包日志明确输出包含Kafka、Clickhouse连接器依赖。解压打好的Jar包,在解压的文件里有Kafka、Clinkhouse连接器的依赖文件。以上确实证明打包将Kafka、Clinkhouse连接器依赖打进提交的应用Jar包中。
提交应用Jar包中既然存在需要的Kafka、Clinkhouse连接器的依赖。怎么提交flink时会报缺少连接器依赖呢?问题出在那里呢?
分析报错的日志,发现两种依赖报错信息是一致的。工程pom.xml的依赖顺序中最前面的连接器都能成功被加载成可用的factory。那这个可用的factory是什么呢。从日志中可以看到是实现了org.apache.flink.table.factories.DynamicTableFactory接口的工厂类。
从上面分析可知,错误来源于没有找到实现org.apache.flink.factories.DynamicTableFactory的工厂。
从源码接口类上注释可以清楚的看到,org.apache.flink.table.factories.Factory是所有种类工厂的基础接口。这些工厂是从Flink’s Table &SQL API的键值对列表实例化的。
拿SQL API来说就就是使用我们定义sql时的with()片段实例化工厂。
为什么会出现META_INF/services/org.apache.flink.table.factories.Factory的文件信息写不全呢?是因为多个依赖构件中的META-INF/services/org.apache.table.factories.Factory文件不能合并造成的。要解决这个问题,还是要回到打包上。
打包使用的是"maven-shade-plugin"打包插件,打包时需要将多个构件中的class文件或资源文件聚合。资源的聚合需要shade插件提供了丰富的Transformer工具类。其中 ServicesResourceTransformer是解决SPI文件的聚合。
加一个transformer:解决问题
<!--JDK的服务发现机制是基于META-INF/services/目录的,如果同一接口存在多个实现需要合并 ,则可以使用此Transformer-->
<configuration>
<transformers>
<transformer implementation="org.apache.maven.plugins.shade.resource.ServicesResourceTransformer"/>
</transformers>
</configuration>