关于Hudi 0.13.1 Streaming Query 报错
org.apache.hadoop.hive.ql.io.parquet.MapredParquetInputFormat ClassNotFoundException
Keywords: Hudi编译Hive,Flink对Hudi进行Streaming Query,Hudi包冲突,编译Hudi
版本:
Hadoop | 3.2.2 |
---|---|
Spark | 3.2.4 |
Flink | 1.16.1 |
Hive | 3.1.3(后回退版本到3.1.2) |
Hudi | 0.13.1(后使用Hudi Github master分支-0.14.0) |
(此处有包冲突,即Hive用的guava.jar版本为guava-19.0.jar,而Hadoop 3.2.2 版本guava.jar版本为guava-27.0-jre.jar)
一般不建议runtime的Hadoop版本高于hive依赖的版本
场景: 使用Flink SQL 对Hudi表进行Streaming Query
官网介绍:使用streaming-query实时查询Hudi表流式数据
CREATE TABLE t2(
uuid VARCHAR(20) PRIMARY KEY NOT ENFORCED,
name VARCHAR(10),
age INT,
ts TIMESTAMP(3),
`partition` VARCHAR(20)
)
PARTITIONED BY (`partition`)
WITH (
'connector' = 'hudi',
'path' = 'hdfs://localhost:9000/hudi-warehouse/hudi-t1',
'table.type' = 'MERGE_ON_READ',
'read.streaming.enabled' = 'true',
'read.start-commit' = '20210316134557',
'read.streaming.check-interval' = '4'
);
当使用Flink Client SQL 对Hudi进行 Streaming Query 时,注意官网Note
The bundle jar with hive profile is needed for streaming query, by default the officially released flink bundle is built without hive profile, the jar needs to be built manually, see Build Flink Bundle Jar for more details.
然后我们此时就必须自己通过Hudi源码编译 hudi-flink1.16-bundle-0.13.1.jar
包
下载Hudi-0.13.1 版本的源码,解压,修改参数编译
但当修改~/hudi-0.13.1/pom.xml
<hadoop.version>3.1.2</hadoop.version>
<hive.groupid>org.apache.hive</hive.groupid>
<hive.version>3.1.3</hive.version>
以及 ~/hudi-0.13.1/packaging/hudi-flink-bundle/pom.xml
<hive.version>3.1.3</hive.version>
....
<profile>
<id>flink-bundle-shade-hive3</id>
<properties>
<hive.version>3.1.3</hive.version>
<flink.bundle.hive.scope>compile</flink.bundle.hive.scope>
</properties>
<dependencies>
<dependency>
<groupId>${hive.groupid}</groupId>
<artifactId>hive-service-rpc</artifactId>
<version>${hive.version}</version>
<scope>${flink.bundle.hive.scope}</scope>
</dependency>
<dependency>
<groupId>${hive.groupid}</groupId>
<artifactId>hive-standalone-metastore</artifactId>
<version>${hive.version}</version>
<scope>${flink.bundle.hive.scope}</scope>
</dependency>
</dependencies>
</profile>
然后
mvn clean install -DskipTests -Pflink-bundle-shade-hive3
时无法构建,报错
[INFO] hudi-hadoop-mr ..................................... FAILURE [ 2.121 s]
.....
[ERROR] Failed to execute goal org.apache.maven.plugins:maven-compiler-plugin:3.8.0:compile (default-compile) on project hudi-hadoop-mr: Compilation failure: Compilation failure:
[ERROR] /Users/kturnura/Packages/hudi-0.13.1/hudi-hadoop-mr/src/main/java/org/apache/hudi/hadoop/utils/HoodieInputFormatUtils.java:[92,50] 无法将类 org.apache.hudi.hadHoodieParquetInputFormat中的构造器 HoodieParquetInputFormat应用到给定类型;
[ERROR] 需要: org.apache.hudi.hadoop.HoodieCopyOnWriteTableInputFormat
[ERROR] 找到: 没有参数
[ERROR] 原因: 实际参数列表和形式参数列表长度不同
[ERROR] /Users/kturnura/Packages/hudi-0.13.1/hudi-hadoop-mr/src/main/java/org/apache/hudi/hadoop/hive/HoodieCombineHiveInputFormat.java:[846,14] 无法将类 org.apache.huadoop.HoodieParquetInputFormat中的构造器 HoodieParquetInputFormat应用到给定类型;
[ERROR] 需要: org.apache.hudi.hadoop.HoodieCopyOnWriteTableInputFormat
[ERROR] 找到: 没有参数
[ERROR] 原因: 实际参数列表和形式参数列表长度不同
[ERROR] /Users/kturnura/Packages/hudi-0.13.1/hudi-hadoop-mr/src/main/java/org/apache/hudi/hadoop/utils/HiveAvroSerializer.java:[302,93] 不兼容的类型: org.apache.hadoopcommon.type.Date无法转换为java.sql.Date
[ERROR] /Users/kturnura/Packages/hudi-0.13.1/hudi-hadoop-mr/src/main/java/org/apache/hudi/hadoop/utils/HiveAvroSerializer.java:[305,72] 不兼容的类型: org.apache.hadoopcommon.type.Timestamp无法转换为java.sql.Timestamp
[ERROR] /Users/kturnura/Packages/hudi-0.13.1/hudi-hadoop-mr/src/main/java/org/apache/hudi/hadoop/utils/HiveAvroSerializer.java:[309,98] 不兼容的类型: org.apache.hadoopcommon.type.Date无法转换为java.sql.Date
[ERROR] /Users/kturnura/Packages/hudi-0.13.1/hudi-hadoop-mr/src/main/java/com/uber/hoodie/hadoop/HoodieInputFormat.java:[26,8] 无法将类 org.apache.hudi.hadoop.HoodiePatInputFormat中的构造器 HoodieParquetInputFormat应用到给定类型;
解决办法
我们在Github找到了本问题的原因 https://github.com/apache/hudi/pull/7173
时间戳无法被Hive3 获取
解决方法一(提供思路,未能尝试成功)
使用patch 合并Contributor 的代码 https://github.com/apache/hudi/files/11574950/5189.patch.zip到本地源码中
测试使用
git apply --check patch/5189.patch
合并到hudi-0.13.1 源码中打补丁失败
git apply --reject file.patch
手动合并,使用这个命令产生冲突无法合并的文件会在~/hudi-0.13.1/hudi-hadoop-mr/src/main/java/org/apache/hudi/hadoop
生成 .rej文件,然后手动合并
可以以下链接参照来逐一修改java文件
https://github.com/apache/hudi/pull/7173/files#diff-cd42bec5495e839654687e99670f40d27defe7178bdd347f23db651fc3262bb7
此处比较迷惑的点是由于Git,使用Hudi-0.13.1源码合并Hudi master分支下的patch包。
还有一个就是尝试过直接copy master分支代码到Hudi 0.13版本在hudi-hadoop-mr/src/main/java/org/apache/hudi/hadoop的代码,但是有新代码添加,无法成功执行
解决办法 二
使用最新源码,同时回退Hive-3.1.2(这是出现另一个问题时Pflink-bundle-shade-hive3 默认指定hive版本为3.1.2,本人尝试多种方式解决减少冲突时回退了版本,但使用该方法使用 hive 3.1.3 应该也可以解决(因为源码中关于Hive 3.1.3 的时间戳))
出现问题:
-
查看许多博客的方法:修改Hudi源码
pom.xml
以及~/hudi/packaging/hudi-flink-bundle/pom.xml
中hadoop.version
和hive.version
版本。但仍然会出现guava.jar 冲突。报错:Caused by: java.lang.NoSuchMethodError: com.google.common.base.Preconditions.checkArgument (ZLjava/lang/String;Ljava/lang/Object;)V.
原因:经过检查发现Hadoop3.1.3 和 hive-3.1.2 的lib下面的guava都是guava-27.0-jre.jar,没有冲突问题。
那就说明只可能是flink/lib下面添加的上面4个jar包中有jar包编译时,引用的guava版本过低导致的。
通过源码锁定了hive-exec-3.1.2.jar 引用了guava-19.0.jar 包,并且 flink-sql-connector-hive-3.1.2_2.11-1.12.0.jar 引用了 hive-exec-3.1.2.jar 参考文献:https://blog.csdn.net/chenshijie2011/article/details/114373468 -
通过上述参考文献编译
Hive-exec-3.1.2.jar
源码并没有解决问题,依然存在冲突
解决方式参考文献: https://www.cnblogs.com/itxiaoshen/p/16934160.html
直接编译文件:具体版本根据个人环境调参
mvn clean package -DskipTests -Dcheckstyle.skip -Dspark3.2 -Dflink1.16 -Dscala-2.12 -Dhadoop.version=3.2.2 -Pflink-bundle-shade-hive3
此时打出的jar包中guava.jar 版本依然为19.0 ,而此时hadoop 的guava.jar 包中的 版本为 guava-27.0-jre.jar
需要拷贝hadoop下的该jar包到flink/lib目录下!!
这是最简单的方式!!!!
有感
该文后续语言比较混乱,有大量试错的过程,原因是在解决该问题的同时用本文记录解决过程,后经过一次简单修改发布了本博客。该问题其实解决方式比较简单,只需要下载Hudi最新源码,编译Hudi,然后复制 guava.jar 到flink/lib目录下即可解决问题。但这个解决问题的过程收获颇多。在编译Hive 和Hudi 诸多版本的源码时也遇到了一些其他的问题,解决一个问题是一个复杂问题的集合。
希望该文能帮到各位