FlinkSQL:source端字段太多导致——64KB问题

FlinkSQL:source端字段太多导致——64KB 问题

Flink 版本1.13,使用 https://github.com/zhp8341/flink-streaming-platform-web平台上传 Job。

背景

需要同步 kafka 数据到 hive 表,但是需要从 kafka 端提取 1500+ 个字段。

提交任务后,显示失败。

在这里插入图片描述

问题追溯

FlinkSQL 提交 Job 后失败,观察 Flink Dashboard 页未产生相应 Job,说明并未上传到 Flink 集群执行。

由此考虑至少没到 TaskManager 处理的阶段,所以排除数据量过大、并行度过低等原因,因为实际上还没开始 source 阶段。

直接看客户端日志,发现关键问题在于:

compiling "StreamExecCalc$3589": Code of method "processElement(Lorg/apache/flink/streaming/runtime/streamrecord/StreamRecord;)V" of class "StreamExecCalc$3589" grows beyond 64 KB

回头来看,这段信息不能说模糊,但确实不确切,在源码里绕了很多路。

最后找遍提到的类和方法,都不及一个 64KB 的信息离问题点近。

于是去 1.13 的源码中找 64KB ,通过 IDEA 的全局查找项目内的 64KB 信息,找到3个:

在这里插入图片描述

其中,TableConfigOptions 和 TableConfig 是我们想看的,因为和 Flinksql 有关。ExecutionConfigOptions 点进去看,可以看到该类中提到的 64 KB 为数据溢写大小。

通过查看 TableConfigOptions 和 TableConfig ,可以发现一句很重要的话:Java has a maximum method length of 64 KB.

在 TableConfigOptions 中发现了修改这个值的配置项 table.generated-code.max-length ,int类型,且最大 64KB 。

在官网上(https://nightlies.apache.org/flink/flink-docs-release-1.13/docs/dev/table/config/)

在这里插入图片描述

找到修改语法:set table.generated-code.max-length=xxx;

因为 64KB 限制的存在,对该配置项做出增大的尝试都是失败告终。

在 flink 的 issue 里,看到这个限制源于: JVM 对方法的编译代码有 64KB 的限制[https://github.com/apache/flink/pull/16349]。

在这里插入图片描述

但同时发现,这个问题有解决办法:https://issues.apache.org/jira/browse/FLINK-23007。

待跟进。。。


2022.09.30

回头看了下这个问题,这次没有去翻源码,而是直接到 issue 里找到了几乎一模一样的问题描述,而且和我们的版本是一致的,打开environment 看,也是 sql 太长导致的这个问题。

https://issues.apache.org/jira/browse/FLINK-22903

在这里插入图片描述

顺着向下走,发现这个问题已被 Flink-23007 解决。

在这里插入图片描述

转到 Flink-23007 页面看下,看到 Fix Version/s:1.14.0,说明在1.14版本该问题被解决,同时在描述里看到:

在这里插入图片描述

解决办法是引入一个后置的基于 antlr4 的 java 类拆分器,来实现分析代码并拆分方法到多个方法的工作。

antlr4是一款基于Java开发的开源的语法分析器生成工具,广泛应用于DSL构建,语言词法语法解析,静态代码分析等领域。

至于第二句,去 1.14 的 CompileUtils 里看了下,发现和1.13没多大区别,看来在 CompileUtils里加入这个拆分器应该只是个建议。

在 1.14 的源码中,发现 flink/flink-table 下,多了个 flink-table-code-splitter 文件夹,看名字像是为了解决类似问题而实现的包。包中有这些类:

在这里插入图片描述

因为我们遇到的问题的根源是 Java 代码过长的问题,所以我们去 JavaCodeSplitter 类中看下:

发现注释写着:

在这里插入图片描述

——重写生成的 java 代码以使每个方法的长度变得更小从而可被编译。

正是我们遇到的问题:方法过长导致编译时就中止报错。

看一下代码:

在这里插入图片描述

split方法,很明显,如果代码小于等于maxMethodLength,就不做变动原样返回。

如果大于这个maxMethodLength这个阈值,就执行splitImpl方法。

我们查下有谁会用到这个方法,看看这个maxMethodLength会是什么值:

在这里插入图片描述

——GeneratedClass

在这里插入图片描述

在TableConfigOptions类里,继续去TableConfigOptions:

然后发现了眼熟的代码:

在这里插入图片描述

同时还发现下面还出现了对类成员变量的限制(先不管这个)。

回到 JavaCodeSplitter 看下怎么拆分的:splitImpl 方法。

在这里插入图片描述

总体是这三步,

  • 对入参做校验
  • 得到代码
  • 对代码做三种rewrite

第三步的这三个类,点进去看,都引用了 antlr4 的包。

splitImpl 的相关源码不再赘述,点进各个类去看,应该是很好分析理解的。

至此,给个结论就是:1.13不行,1.14行。

当然,回到https://issues.apache.org/jira/browse/FLINK-23007页面,其实这个问题,还没有完全被解决。。。

在这里插入图片描述

评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值