【Flink系列九】Flink 作业提交遇到的问题记录以及原理

起因

  • 由于近期研究了ElasticSearch的Connector,但是目前生产环境不需要此jar。
  • Flink社区的一些小伙伴交流的时候,发现有人在使用Flink Session-Cluster模式提交作业,正好发现自己缺少这块知识细节。
  • 虑到Yarn集群不可用,或者没有Yarn的开发环境下,有Flink Session Cluster也是一个不错的使用环境。

带着折腾的目的,故意舍近求远。

需求

研究ES和CDC的使用,需要flink-sql-connector-cdc和flink-sql-connector-elasticsearch,但需要考虑不同用户共享一个Flink客户端,且希望Connectors是可插拔的。

问题记录

org.apache.flink.table.api.ValidationException: Could not find any factory for identifier 'mysql-cdc' that implements 'org.apache.flink.table.factories.DynamicTableSourceFactory' in the classpath

※此问题网络上有一些解决方案

例如 maven-shade-plugin

ini 复制代码
<transformer implementation="org.apache.maven.plugins.shade.resource.ServicesResourceTransformer"/>

仅看这个错误,是不够的,无法确定是 Source的问题,还是Classpath的问题。还需要分析操作场景,才能找到真实原因。

SPI 导致的问题

如果是在开发自定义Flink Source/Sink的时候遇到此问题,则问题可能是SPI加载机制。

  • 需要确保打的jar包 META-INF/services提供完整的信息。
    • 确保Classpath加载没有问题的情况下

Classpath导致的问题

如果是下载了新的Connector,例如官方提供的、Ververica提供的,则问题可能是classpath加载问题。

  • 如果是Yarn-Per-job模式提交作业,则需要确保所有涉及的Connector,包括FlinkSQL的connector,以及 TableAPI直接引用到的Connector,都以恰当的方式提交到Yarn集群。

    • 例如 flink yarn-per-job模式 flink run 的参数 -C, -yt
  • 如果是Session-Cluster模式提交作业,例如Standalone-Session模式,启动集群的时候就要指定Connector的Classpath。

    • 正常情况下,都需要放在FLINK_DIST_DIR/lib内。

    • Session-Cluster模式需要重启。

  • 如果是Yarn-Application模式提交作业

    • flink run-application 的参数 -C

    • 也需要指定正确的 yarn.provided.lib.dirs ,例如 viewfs://slankka11/applications/flink-1.13.0/lib;viewfs://slankka11/applications/flink-1.13.0/plugins;

实践

在实践过程中,此问题显而易见,ververica文档就说了,把jar放进lib内。

但是,舍近求远,由于平台项目本身用到了额外的目录存放这些Connector,并希望和lib区分开来。

注:由于目标是平台化,平台的Flink客户端因为是共享的,因此没有将 Connectors,User的Library放在 lib。

问题就来了,如果放在其他的目录怎么办呢?

  • 这里是用的Standalone-Cluster方式,且jar依赖放在了Connectors内,和lib分开了。

原理

Flink的bin/config.sh,是bin内的脚本的配置读取入口,内置了一些处理classpath的bash shell function。

  • 生效的方式为:. config.sh,这就是一个source命令。
  • bin/start-cluster.sh 以及 bin/flink 等脚本都依赖这个脚本中的一个function,也就是
bash 复制代码
constructFlinkClassPath() {
    local FLINK_DIST
    local FLINK_CLASSPATH
    ...
}

这个类其实就是找出了 flink-dist.jar,以及lib下的jar,生成一个classpath字符串。

※ 模仿FLINK_CLASSPATH, 将connectors目录下的jar导入到classpath内。

bash 复制代码
local FLINK_CONNECTORS
while read -d '' -r jarfile ; do
        if [[ "$jarfile" =~ .*/flink-dist[^/]*.jar$ ]]; then
            :
        elif [[ "$FLINK_CONNECTORS" == "" ]]; then
            FLINK_CONNECTORS="$jarfile";
        else
            FLINK_CONNECTORS="$FLINK_CONNECTORS":"$jarfile"
        fi
    done < <(find "$FLINK_LIB_DIR/../connectors" ! -type d -name '*.jar' -print0 | sort -z)

echo "$FLINK_CLASSPATH"":$FLINK_CONNECTORS""$FLINK_DIST"

$FLINK_CONNECTORS插入到其中。

接下来,重启cluster,再次提交flink作业即可解决此问题。同时,能解决所有这类问题。

额外的信息:

  • flink作业的jar依赖都用的 scope=provide
  • flink作业的jar的SPI没有关于mysql-cdc的相关定义。

即便如此,也能正确提交作业。


2023.10.20 批注

Flink 逐步淘汰了 yarn-per-job的部署方式,未来推荐使用 yarn-application方式。

后者推荐使用 yarn.provided.lib.dirs 指定依赖。

相关推荐
快乐肚皮1 天前
深入理解Loop Engineering
前端·后端
小兔崽子去哪了1 天前
Vue3 + Pinia 集成 IGV.js 实现 BAM 文件在线浏览
javascript·vue.js·后端
孟陬1 天前
Claude Code 巧思 `Ctrl+S` 暂存键
前端·后端
雪隐1 天前
个人电脑玩AI-06让5060 Ti给你打工——不光能画画,Qwen3-TTS还能学人说话,连我老板都信了!
人工智能·后端·python
Oneslide1 天前
openEuler 17.1GB Everything ISO 离线本地 DNF 源搭建教程
后端
蝎子莱莱爱打怪1 天前
那不是我的黑历史,那是我的来时路啊!😭😭
后端·程序员
用户298698530141 天前
Java 实现 Word 文档文本与图片提取的方法
java·后端
蝎子莱莱爱打怪1 天前
XZLL-IM干货系列 04|Netty 长连接实战:Pipeline 怎么排、心跳怎么跳、连接怎么管
后端·微服务·面试
Csvn1 天前
Rsync 文件同步与增量备份 — 运维的数据守门员
后端
苏三说技术1 天前
推荐一个牛逼的智能代码审查系统
后端