浅析 hive udf 的正确编写和使用方式- 论姿势的重要性 - 系列三 - hdfs 相对路径与静态代码块引起的问题

简介: 浅析 hive udf 的正确编写和使用方式- 论姿势的重要性 - 系列三 - hdfs 相对路径与静态代码块引起的问题

前言

大家好,我是明哥。

HIVE 作为大数据生态的数仓解决方案,因为历史的原因在很多行业很多公司都有着广泛的应用。对于比较复杂的业务逻辑,HIVE SQL 往往比较难以表达,此时大家在开发中往往会辅以 HIVE UDF。所以充分理解和掌握 HIVE UDF正确的表写和使用方式,是大数据从业人员必不可少的一项技能。

关于HIVE UDF 的使用,明哥在前段时间发过两篇博文,分别是 “如何在 hive udf 中访问配置数据-方案汇总与对比” 和 “浅析 hive udaf 的正确编写方式- 论姿势的重要性" ,两篇博文描述的都是 HIVE UDF 在编写使用过程中容易犯的错误。

但 UDF 编写使用过程中遇到的问题往往很多远远不止以上两个,所以明哥决定编写一个系列 - “浅析 hive udf 的正确编写和使用方式 - 论姿势的重要性“,以上两篇博文可以算做这个系列中的系列一和系列二,本文是该系列的系列三。 以下是正文。

时间紧张急于知道结论的小伙伴,可以直接看最后一部分,问题总结。

问题现象与初步分析

产品部人员反馈,某 HIVE UDF 通过 hive 的旧客户端即 hive service --cli方式可以正常使用,但使用新客户端 beeline 时却会报错,客户端的报错信息没有啥明确的有意义的信息,如下图图一和图二所示:

image.png

咨询产品部开发人员,该 UDF 的功能是返回给定业务日期的下一个业务日期,在背后会读取 HDFS上的一个日期类配置文件;经查看该 UDF 源码,发现该日期类配置文件的路径,使用的是相对路径,如下图所示:

image.png

熟悉 HDFS 的小伙伴都知道 HDFS 有相对路径的概念,即代码中用相对路径方式指定的文件, 在不同用户执行作业时会被解析为不同用户的根目录下的文件,比如相对路径 dir1/fileA, 使用hive 用户执行时作业时会被解析为 /user/hive/dir1/fileA, 使用xyz用户执行作业时会被解析为 /user/xyz/dir1/fileA, 很多 hdfs 上的文件找不到的问题都是因为该原因。因为有的环境有的用户能执行成功而另外的环境另外的用户执行却会失败,我们往往戏谑是人品问题,哈哈。

所以顺藤摸瓜,看到这里有使用相对路径指定文件,我们一个自然的思路是查看日志验证问题。需要注意,这里要查看的是服务端的日志,即 beeline 连接的 hiveserver2 实例的日志,在 cdh 中一般是 /var/log/hive下。果不其然,看到了熟悉的报错信息:

image.png

进一步咨询产品部人员,他们把该配置文件上传到了 /user/root/ 目录下,没有上传过其它目录。这也解释了,为什么 他们 hive service --cli 方式能够成功,而 beeline方式如 beeline -u jdbc:hive2://xxx:10000/default -n userA -p passwd 方式却会失败:因为他们使用前者时是固定在 root 登录用户的身份下提交的作业(这其实不太合规范,一般不建议用root身份运行应用程序),而使用后者时实际生效的用户是 -n 参数指定的用户而不是当前登录用户!(没有启用用户身份认证或启用ldap认证时,都是通过 -n 参数指定用户身份;启用kerberos认证时,通过kerberos的 principal指定用户身份)。这里还有个小细节,如果没有启用身份认证且 beeline后没有使用 -n参数指定用户,真正生效的用户时anonyous匿名用户,对应的 home directory 是 /user/anonymous.

分析到这里,我们觉得只需要上传该配置文件到对应用户的 home directory下,即可解决该问题了。但实际验证发现,啪啪打脸,同样的问题仍然存在!

问题进一步分析

再次仔细查看相关代码,发现了问题所在:该 UDF 读取配置文件的内容,使用的是类的静态代码块(不是静态方法)。为什么使用静态代码块会引起问题?要回答这个问题,需要比较扎实的 JAVA 功底, 和对 UDF 执行机制的深刻理解。小伙伴们可以下想下。

image.png

不卖关子,直接说原因:我们知道 SQL 和 UDF 的解析编译优化和生成 mr/tez/spark 任务是在 hiveserver2 中进行的,但并不是所有的 sql 和 udf 都会生成 mr/tez/spark 任务,比如这里该 UDF就不会生成 mr/tez/spark 任务,也不需要向 yarn 申请资源获得 container 容器,而是直接在 hiveserver2 中执行的。所以前几次 UDF的失败调用时,该 hiveserver2 这个jvm 已经加载了对应的类,此次再次调用该 UDF 时不需要重新加载该类,自然也不会重新执行类的静态代码块,所以没有重新读取配置文件的内容,所以没有更新对应的配置变量,执行也就失败了。

重新启动该 hiveserver2 实例后,再次提交该 udf,会重新加载对应的类,并执行其中的静态代码块读取配置文件的内容,读取成功后会更新对应的配置变量,最后作业执行成功。

问题总结

  • HDFS 有相对路径的概念,即代码中用相对路径方式指定的文件, 在不同用户执行作业时会被解析为不同用户的根目录下的文件,比如相对路径 dir1/fileA, 使用hive 用户执行时作业时会被解析为 /user/hive/dir1/fileA, 使用xyz用户执行作业时会被解析为 /user/xyz/dir1/fileA, 很多 hdfs 上的文件找不到的问题都是因为该原因;
  • Hive SQL 和 UDF 的解析编译和优化是在 hiveserver2 中进行的,解析编译和优化的结果一般是生成 mr/tez/spark 任务,这些 mr/tez/spark 任务是在向 yarn 申请获得的 container 容器对应的 jvm 中执行的;但并不是所有的 sql 和 udf 都会生成 mr/tez/spark 任务,此时其真正的执行就是直接在 hiveserver2 这个已经存在的 jvm 中执行的,该 hiveserver2 这个 jvm 的生命周期跟 udf 的执行无关,如果涉及到配置环境变量,系统参数,或加载类及执行静态代码块,要尤其小心,必要时需要重启 hiveserver2;(udf 中需要谨慎只用静态代码块,因为静态代码块只有在初次加载类的时候才会执行)
  • udf中读取配置文件,有多种方式,常见的有:
  • 配置文件使用绝对路径指定,且在代码中写死绝对路径;
  • 配置文件使用绝对路径,但在代码中通过读取本地配置文件获取hdfs上配置文件的最终绝对路径;
  • 配置文件使用相对路径,在客户现场部署时需要确定执行作业的真正用户身份,并上传该配置文件到对应用户的跟目录下的特定路径;
相关文章
|
2月前
|
SQL 关系型数据库 MySQL
Sqoop【付诸实践 01】Sqoop1最新版 MySQL与HDFS\Hive\HBase 核心导入导出案例分享+多个WRAN及Exception问题处理(一篇即可学会在日常工作中使用Sqoop)
【2月更文挑战第9天】Sqoop【付诸实践 01】Sqoop1最新版 MySQL与HDFS\Hive\HBase 核心导入导出案例分享+多个WRAN及Exception问题处理(一篇即可学会在日常工作中使用Sqoop)
95 7
|
12天前
|
SQL Java 数据处理
【Hive】Hive的函数:UDF、UDAF、UDTF的区别?
【4月更文挑战第17天】【Hive】Hive的函数:UDF、UDAF、UDTF的区别?
|
3月前
|
SQL 消息中间件 Apache
Flink报错问题之使用hive udf函数报错如何解决
Apache Flink是由Apache软件基金会开发的开源流处理框架,其核心是用Java和Scala编写的分布式流数据流引擎。本合集提供有关Apache Flink相关技术、使用技巧和最佳实践的资源。
|
4月前
|
SQL 搜索推荐 Java
Hive中的UDF是什么?请解释其作用和使用方法。
Hive中的UDF是什么?请解释其作用和使用方法。
39 0
|
5月前
|
SQL 分布式计算 Java
Hive自定义函数UDF编写
Hive自定义函数UDF编写
35 2
|
5月前
|
SQL 分布式计算 Hadoop
[AIGC ~大数据] 深入理解Hadoop、HDFS、Hive和Spark:Java大师的大数据研究之旅
[AIGC ~大数据] 深入理解Hadoop、HDFS、Hive和Spark:Java大师的大数据研究之旅
|
5月前
|
存储 SQL 分布式计算
Hadoop(HDFS+MapReduce+Hive+数仓基础概念)学习笔记(自用)
Hadoop(HDFS+MapReduce+Hive+数仓基础概念)学习笔记(自用)
269 0
|
7月前
|
SQL 分布式计算 Java
阿里云MaxCompute-Hive UDF(Java)迁移上云实践
阿里云MaxCompute-Hive UDF(Java)迁移上云实践
|
7月前
|
SQL 分布式计算 大数据
大数据问题排查系列 - 因HIVE 中元数据与HDFS中实际的数据不一致引起的问题的修复
大数据问题排查系列 - 因HIVE 中元数据与HDFS中实际的数据不一致引起的问题的修复
|
7月前
|
SQL 分布式计算 Java
如何在 hive udf 中访问配置数据-踩坑记录,方案汇总与对比-udf中可以写sql吗?
如何在 hive udf 中访问配置数据-踩坑记录,方案汇总与对比-udf中可以写sql吗?

热门文章

最新文章