文章目录

  • 一、问题描述
  • 二、排查过程
    • 1. 梳理hive程序的执行流程
    • 2. 推测问题产生的原因
    • 3. 通过arthas找出罪魁祸首
    • 4. 问题总结和解决办法
  • 三、个人反思和一些总结

想直接看结论和解决方案的同学可以直接跳到2.4章节

一、问题描述

前几天有用户反馈将hive查询结果以orc导入到hdfs目录时出现异常,sql大概如下:

insert overwrite directory '/tmp/' stored as orc
select * from x_table;

异常显示是在查询结束要写入orc文件时出现NullPointException。

对这个问题感兴趣的同学可以看我的这篇博客:

hive insert overwrite directory 问题排查

简单的做了几次模拟,发现有些数据可以,比如说把"*"号改成某些字段。很自然的觉的可能是数据的问题,所以最开始的想法是在orc的出错的源码周围打点日志,顺便判断以为空就跳过不处理同时把那条数据打印出来。于是从github上下载了orc的源码,开始改代码,然后编译打包,放到测试机器的hive/lib下。最后再执行出错语句时,发现异常信息还是一样,连出错的行数都没变化,日志也没输出。这就s说明orc-core.jar替换没生效,hive运行时没有加载这个jar

所以问题总结就是:

  • 替换了hive/lib下面的jar包,重启hive后新的jar包还是没生效的问题。

二、排查过程

备注:我们的hive是跑在yarn上面的,一般是用spark作为执行引擎

1. 梳理hive程序的执行流程

我们都知道,hive在执行sql的时候,会解析语法树,然后构造执行计划,接着做一些优化,最后会生成spark或者mapred job执行任务。所以我们hive任务是在yarn上的各个container上执行的。由于我们的执行引擎设置的是spark,所以最好先了解一下hive是怎么提交生成的spark job到yarn上面执行的。

看了一圈hive源码后,大概理通了spark的提交流程。

如果我们在配置文件中指定了spark.master=yarn,hive在真正执行任务的时候会通过spark-submit往yarn提交spark job。我们可以在hive.log的日志中看到以下日志:

2019-01-22T11:20:54,268  INFO [Thread-23] spark.client.SparkClientImpl:469 Running client driver with argv: /www/spark/bin/spark-submit --executor-cores 2 --executor-memory 6g --properties-file /tmp/spark-submit.7734574653075860835.properties --class org.apache.hive.spark
.client.RemoteDriver /www/apache-hive-2.3.3-bin/lib/hive-exec-2.3.3-yangjb-0121.1.jar --remote-host dn162 --remote-port 13719 --conf hive.spark.client.connect.timeout=10800000 --conf hive.spark.client.server.connect.timeout=36000000 --conf hive.spark.client.channel.log.le
vel=null --conf hive.spark.client.rpc.max.size=52428800 --conf hive.spark.client.rpc.threads=8 --conf hive.spark.client.secret.bits=256 --conf hive.spark.client.rpc.server.address=null

了解spark的同学应该很容易看的出来,这就是标准的spark往yarn提交任务的命令。

插个题外话,稍微介绍一下hive运行spark job的流程:

往yarn提交了一个任务执行RemoteDriver这个类的main方法,这个类会在集群中以客户端的方式去连接hive这边启动的服务端rpc。之后hive进程和集群中的RemoteDriver就通过netty rpc的方式来沟通,包括发送执行的spark work等。

2. 推测问题产生的原因

知道hive是如何执行的后,就可以开始查找为什么orc.jar包不生效了。既然是在yarn的container上面执行spark job,我们就要看下orc的jar包是在yarn直接指定的classpath里面,还是提交spark job时直接指定classpath中

我首先先搜了一圈yarn对应的所有classpath,甚至连java的lib都看了,发现并没有orc包

接着看spark提交job时执行的配置文件/tmp/spark-submit.7734574653075860835.properties。发现有一行配置,应该就是spark job执行时指定的classpath了。

spark.yarn.jars hdfs://lrtscluster/data/spark2_2_2/*

但是去这个hdfs目录下找了一圈,发现也没有对应的orc包。这时候就很蒙圈了,既然都没有orc包,那hive任务运行时是如何加载orc的类的呢。(这里可以百分比确认出错的类是orc包下面的类)

后面又看了几圈yarn和hive、spark的配置,都没有发现有哪个地方可能有这个orc包,所以只能动用工具来排查这个类到底出自哪个jar包的了。

3. 通过arthas找出罪魁祸首

arthas是一款jvm相关问题排查工具,arthas的使用不在这里介绍,不了解的同学可以看我的这篇博客:

JVM进程诊断利器——arthas介绍

主要流程就是观察到spark在某个container上执行时,立马将arthas安装到目标机器上,然后attach到该container进程中排查。

最后通过命令排查到所有已加载的orc类

sc -d *.orc.impl.*

发现加载这些类的jar包竟然是一个叫/tmp/xxx/__app.jar__的类。yarn要运行job时,会收集相关的信息到一个临时目录,里面包括跑job要依赖的jar包等。这个\_\_app.jar\_\_包就在这个临时目录下。最后在进入这个目录看,发现这个包竟然是hive-exec-xxx.jar的一个软连接。

突然之间恍然大悟,跑去看了下hive的ql模块的pom文件,发现以下这些代码:

 <plugin>                                                                              <groupId>org.apache.maven.plugins</groupId>                                         <artifactId>maven-shade-plugin</artifactId>                                         <executions>                                                                        <execution>                                                                       <id>build-exec-bundle</id>                                                      <phase>package</phase>                                                          <goals>                                                                         <goal>shade</goal>                                                            </goals>                                                                        <configuration>                                                                 <!--also see maven-jar-plugin execution.id=core-jar-->                      <artifactSet>                                                                 <includes>                                                                  <!-- order is meant to be the same as the ant build -->                   <include>org.apache.hive:hive-common</include>                            <include>org.apache.hive:hive-exec</include>                              <include>org.apache.hive:hive-serde</include>                             <include>org.apache.hive:hive-llap-common</include>                       <include>org.apache.hive:hive-llap-client</include>                       <include>org.apache.hive:hive-metastore</include>                         <include>org.apache.hive:hive-service-rpc</include>                       <include>com.esotericsoftware:kryo-shaded</include>                       <include>com.esotericsoftware:minlog</include>                                    <include>org.objenesis:objenesis</include>                                        <include>org.apache.parquet:parquet-hadoop-bundle</include>               <include>org.apache.thrift:libthrift</include>                            <include>org.apache.thrift:libfb303</include>                             <include>javax.jdo:jdo-api</include>                                      <include>commons-lang:commons-lang</include>                              <include>org.apache.commons:commons-lang3</include>                       <include>org.jodd:jodd-core</include>                                     <include>com.tdunning:json</include>                                      <include>org.apache.avro:avro</include>                                   <include>org.apache.avro:avro-mapred</include>                            <include>org.apache.hive.shims:hive-shims-0.23</include>                  <include>org.apache.hive.shims:hive-shims-0.23</include>                  <include>org.apache.hive.shims:hive-shims-common</include>                <include>com.googlecode.javaewah:JavaEWAH</include>                       <include>javolution:javolution</include>                                  <include>com.google.protobuf:protobuf-java</include>                      <include>io.airlift:aircompressor</include>                               <include>org.codehaus.jackson:jackson-core-asl</include>                  <include>org.codehaus.jackson:jackson-mapper-asl</include>                <include>com.google.guava:guava</include>                                 <include>net.sf.opencsv:opencsv</include>                                 <include>org.apache.hive:spark-client</include>                           <include>org.apache.hive:hive-storage-api</include>                       <include>org.apache.orc:orc-core</include>                                <include>org.apache.orc:orc-tools</include>                               <include>joda-time:joda-time</include>                                    </includes>                                                                 </artifactSet>                                                                <relocations>                                                                 <relocation>                                                                <pattern>com.esotericsoftware</pattern>                                   <shadedPattern>org.apache.hive.com.esotericsoftware</shadedPattern>       </relocation>                                                               <relocation>                                                                <pattern>org.objenesis</pattern>                                          <shadedPattern>org.apache.hive.org.objenesis</shadedPattern>              </relocation>                                                               </relocations>                                                                </configuration>                                                                </execution>                                                                      </executions>                                                                       </plugin>

上面的代码会将指定的依赖包打进hive-exec-xx.jar里面

4. 问题总结和解决办法

hive在打包hive-exec-xx.jar时会将一些相关的依赖打进去,也就是FatJar,这就导致我们更换hive/lib的一些第三方jar包不生效的问题

要解决这个问题,个人认为有两种办法:

  1. 如果就涉及一些类的话,直接编译完这些类后,替换jar包里面的指定类。这个通过zip命令可以实现对jar包文件的增删改。
  2. 自己编译一个新的版本,然后改一下hive的源码,版本改成自己编译的,之后再编译一遍hive

三、个人反思和一些总结

  1. 对hive的了解还不够深入。如果足够熟悉hive的话,这应该是个很简单的问题,要能快速解决才对,花了几个小时排查不太应该
  2. 个人认为hive打包的方式有问题,不是说不应该打FatJar,而是既然打了FatJar,又将那些第三方jar包放进lib中,导致开发或运维以为可以直接更换第三方jar包。——其实把这些第三方jar包都删了也不会影响hive运行

hive 替换第三方jar包不生效 问题排查相关推荐

  1. docker添加jar包_Maven系列教材 (七)- 如何添加第三方jar包

    Maven系列教材 (七)- 如何添加第三方jar包 步骤1:Maven项目用到第三方jar步骤2:修改App步骤3:给maven项目添加jar步骤4:保存再执行步骤5:重建本地仓库 步骤 1 : M ...

  2. Android Studio 在项目中引用第三方jar包

    在Android Studio项目中引用第三方jar包的方法: 步骤: 1.在build.gradle文件中添加如下代码: 备注:要添加在Android作用域下 sourceSets {main {j ...

  3. cmd库的导入Java,在cmd命令窗口导入第三方jar包来运行java文件

    在cmd命令窗口导入第三方jar包来运行java文件,以下测试都是基于window环境,Linux环境没有测试. 1.编译 使用命令javac -cp或者javac -classpath 本机测试:如 ...

  4. Eclipse导出可执行Jar文件(包含第三方Jar包)

    为什么80%的码农都做不了架构师?>>>    1. 首先,右键你的Java工程,选择Export,在Java文件夹下选择Runnable JAR file,如下图所示: 2. 选择 ...

  5. java导入包写在第二行的吗_使用Java命令行方式导入第三方jar包来运行Java程序的命令...

    1.首先使用命令行进入到a.java所在的文件夹:(比如我的在D:\javaeeworkspace\SharedPS_WS\src\com\dyf\main 这样一个路径下,) d: 回车, cd D ...

  6. Android笔记:防反编译、代码混淆中,解决第三方jar包不被混淆的一些心得,及gson防混淆方法...

    为了防止代码被反编译,一般在签名导出前需要对代码进行混淆.最近发现自己的一个项目工程在代码混淆后,使用中出现了异常.以下是自己这几天在解决代码混淆以及引入第三方jar包导致混淆出现的问题处理的一些心得 ...

  7. android支持第三方jar包,以及Eclipse如何导入jar包

    2019独角兽企业重金招聘Python工程师标准>>> 通常我们进行android开发的时候运用到了两种格式的jar包文件. 1.在eclipse环境下,引入第三方jar包,指的是通 ...

  8. Android安卓开发-eclipse正确添加第三方jar包

    本文转载自http://www.cnblogs.com/developerY/archive/2013/04/18/3027997.html,在此对原作者表示感谢! 在android项目中添加第三方j ...

  9. 怎样在android平台上使用第三方jar包

    网上查都说是通过添加中Build Path或者使用User library来添加,我不知道这些复杂粘贴的人测试过没,反正我测试了好久都不行,估计是我RP不行,这样添加到后编译会通过,但运行的时候就会提 ...

最新文章

  1. 迄今为止程序员写过的最大Bug:亏损30亿、致6人死亡,甚至差点毁灭世界
  2. JQuery读书笔记--JQuery-Form中的AjaxForm和AjaxSubmit的区别
  3. 计算机主机电池,为什么电脑主机板上面有电池?很多人可能根本不知道
  4. 腾讯工作心得:原型该画到什么程度?
  5. 彻底禁用resource manager
  6. 第一章 计算机系统概述 1.1 计算机发展史 [计算机组成原理笔记]
  7. PP视频如何关闭下载完成通知我
  8. JAVA利用JXL导出/生成 EXCEL1
  9. 路径空间HDOJ 4514 - 湫湫系列故事——设计风景线 并查集+树型DP
  10. 网络管理助力节约IT运维成本
  11. Android 地图跳转到百度、高德、腾讯地图导航
  12. Excel 简单线性回归图表制作
  13. 由火车上的查票事件所引起的思考
  14. 禁止小程序输入Emoji表情符
  15. django自带模块实现翻页功能
  16. php两个图片并排显示,wordpress文章图片怎么并排
  17. input 起止时间_完整的时间(开始和结束时间)输入框验证js
  18. 迷你计算机主板,打造最强MINI主机 五款高规ITX主板推荐
  19. 数模每日小练习——数据处理——插值
  20. 移动安全学习笔记——组件安全之ContentProvider组件漏洞挖掘

热门文章

  1. Spring Cloud Feign的原理及基本使用
  2. 为什么txt文件加.c后缀还是txt文件而不是c文件
  3. 三菱880彩铅和uni的区别_想要花卉作品更有层次感?不妨试试三菱uni彩铅!
  4. swust 1646 迷宫与宝藏
  5. 需求变更控制流程的十大步骤
  6. 基于java电子病历系统计算机毕业设计源码+系统+lw文档+mysql数据库+调试部署
  7. 电大计算机组成原理期末考试试题及答案,最新电大计算机组成原理期末考试试题及答案小抄‌.doc...
  8. 机器学习流程错误分析
  9. oracle r12 税,Oracle EBS R12 总账和子分类帐关系详解
  10. 一文详解自动驾驶V2X车联网技术丨曼孚科技