avatar

目录
Hive源码调试

[toc]

1、概述

  最近用到了Hive Hook的一些功能,每次打包后都要将jar包拷贝到CDH集群中,还要重启Hive,很麻烦。且传入Hook类中的HookContext对象用Json工具类转换成Json时某些情况下有问题,想看其中的具体内容很不方便。尝试用alibaba的arthas工具attach到hiveserver2上通过monitor方法查看参数,发现该工具无法打印层次太深的成员变量。So,研究了一下Hive源码调试方法,这样在调试Hive Hook这类应用比较方便,如果后续要看Hive内部原理之类的,也方便通过调试学习。

  本文介绍的方法通过搭建一个单节点hadoop,然后编译Hive源码,通过hive启动相关hive服务时,在要调试的hive服务的启动命令中添加–debug选项,通过远程调试的方式来调试Hive的相关服务。(不知道网上有些地方说的不需要hadoop能否运行哈,反正我没试成功)

  使用的Hive版本为CDH6.3.0对应的hive版本。

2、安装Hadoop

  简单配置一个可用的单节点hadoop即可。

2.1 下载及配置

  • 下载hdaoop3.0.0,解压并修改配置文件:
  • hadoop-env.sh添加JAVA_HOME
    Code
    1
    export JAVA_HOME=/usr/lib/jvm/java-8-openjdk-amd64
  • core-site.xml
    Code
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    <configuration>
    <property>
        <name>fs.default.name</name>
        <value>hdfs://kali:9000</value>
      </property>
      <property>
        <name>hadoop.tmp.dir</name>
        <value>file:///root/tool/BD/hadoop.data.dir/tmp</value>
      </property>
    <property>
    <name>hadoop.proxyuser.sqoop2.hosts</name>
    <value>*</value>
    </property>
    <property>
    <name>hadoop.proxyuser.sqoop2.groups</name>
    <value>*</value>
    </property>
    <property>
    <name>hadoop.proxyuser.root.hosts</name>
    <value>*</value>
    </property>
    <property>
    <name>hadoop.proxyuser.root.groups</name>
    <value>*</value>
    </property>
    <property>
    <name>fs.file.impl</name>
    <value>org.apache.hadoop.fs.LocalFileSystem</value>
    </property>
    <property>
    <name>fs.hdfs.impl</name>
    <value>org.apache.hadoop.hdfs.DistributedFileSystem</value>
    </property>
    </configuration>
  • hdfs-site.xml
    Code
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    <configuration>
    <property>
        <name>dfs.replication</name>
        <value>1</value>
      </property>
      <property>
        <name>dfs.namenode.name.dir</name>
        <value>file:///root/tool/BD/hadoop.data.dir/dfs/name</value>
      </property>
      <property>
        <name>dfs.datanode.data.dir</name>
        <value>file:///root/tool/BD/hadoop.data.dir/dfs/data</value>
      </property>
      <property>
        <name>dfs.namenode.secondary.http-address</name>
        <value>kali:9001</value>
      </property>
    </configuration>
  • mapred-site.xml
    Code
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    <configuration>
    <property>
         <name>mapreduce.framework.name</name>
         <value>yarn</value>
       </property>
    <property>
    <name>mapreduce.jobhistory.address</name>
    <value>kali:10020</value>
    </property>
    <property>
    <name>mapreduce.map.memory.mb</name>
    <value>1024</value>
    </property>
    <property>
    <name>mapreduce.reduce.memory.mb</name>
    <value>2048</value>
    </property>
    <property>
    <name>yarn.app.mapreduce.am.env</name>
    <value>HADOOP_MAPRED_HOME=/root/tool/BD/hadoop-3.0.0</value>
    </property>
    <property>
    <name>mapreduce.map.env</name>
    <value>HADOOP_MAPRED_HOME=/root/tool/BD/hadoop-3.0.0</value>
    </property>
    <property>
    <name>mapreduce.reduce.env</name>
    <value>HADOOP_MAPRED_HOME=/root/tool/BD/hadoop-3.0.0</value>
    </property>
    </configuration>
  • yarn-site.xml
    Code
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    <configuration>

    <!-- Site specific YARN configuration properties -->
    <property>
    <name>yarn.acl.enable</name>
    <value>0</value>
    </property>
    <property>
    <name>yarn.resourcemanager.hostname</name>
    <value>kali</value>
    </property>
    <property>
    <name>yarn.nodemanager.aux-services</name>
    <value>mapreduce_shuffle</value>
    </property>
    <property>
    <name>yarn.log-aggregation-enable</name>
    <value>true</value>
    </property>
    <property>
    <name>yarn.log-aggregation.retain-seconds</name>
    <value>604800</value>
    </property>

    <property>
    <name>yarn.nodemanager.vmem-check-enabled</name>
    <value>false</value>
    </property>
    <property>
    <name>yarn.app.mapreduce.am.resource.mb</name>
    <value>1024</value>
    </property>
    <property>
    <name>yarn.scheduler.minimum-allocation-mb</name>
    <value>1024</value>
    </property>
    <property>
    <name>yarn.scheduler.maximum-allocation-mb</name>
    <value>4096</value>
    </property>
    <property>
    <name>yarn.nodemanager.resource.memory-mb</name>
    <value>16384</value>
    </property>
    </configuration>

    2.2 配置环境变量

    Code
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    # 启动hive时提示需要配置
    export HADOOP_HOME=/root/tool/BD/hadoop-3.0.0
    # 用root用户启动hadoop提示需要配置用户
    export HDFS_NAMENODE_USER=root
    export HDFS_DATANODE_USER=root
    export HDFS_SECONDARYNAMENODE_USER=root
    export YARN_RESOURCEMANAGER_USER=root
    export YARN_NODEMANAGER_USER=root
    export HADOOP_MAPRED_HOME=$HADOOP_HOME
    export HADOOP_YARN_HOME=$HADOOP_HOME

    export PATH=$PATH:$HADOOP_HOME/sbin:$HADOOP_HOME/bin

    2.3 格式化namenode

    Code
    1
    $HADOOP_HOME/sbin/hdfs namenode -format

    2.4 启动hdoop

    Code
    1
    $HADOOP_HOME/sbin/start-all.sh
      确保yarn的ResourceManager、NodeManager,hdfs的NameNode、SecondaryNameNode、DataNode服务启动即可。

    3、编译Hive

    3.1 编译

      克隆cloudera/hive仓库,切换到cdh6.3.0分支(当前使用的版本),可以设置一下项目根目录下的pom.xml中的仓库地址,换成比较快的仓库,然后在项目根目录下执行mvn clean package -DskipTests -Pdist,构建可发布的tar包。运行完后生成的文件在packagine [hive-package]模块中,如下为相关文件列表:
    Code
    1
    2
    3
    4
    drwxrwxrwx 1 root root         0 Mar 17 08:58 apache-hive-2.1.1-cdh6.3.0-bin
    -rwxrwxrwx 1 root root 207735011 Mar 17 08:58 apache-hive-2.1.1-cdh6.3.0-bin.tar.gz
    -rwxrwxrwx 1 root root 25238408 Mar 17 08:59 apache-hive-2.1.1-cdh6.3.0-jdbc.jar
    -rwxrwxrwx 1 root root 19744989 Mar 17 08:59 apache-hive-2.1.1-cdh6.3.0-src.tar.gz

    3.2 配置hive

      打包后,packaging/target/apache-hive-2.1.1-cdh6.3.0-bin/apache-hive-2.1.1-cdh6.3.0-bin目录下是未压缩的相关hive文件,后续操作可以都在这个目录下执行,所以后面以该目录为当前目录

  拷贝一个配置文件,cp conf/hive-default.xml.template conf/hive-site.xml,在conf/hive-site.xml中修改或添加一些必要的配置:

Code
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
<property>
<name>system:java.io.tmpdir</name>
<value>/tmp/hive/java</value>
</property>
<property>
<name>system:user.name</name>
<value>${user.name}</value>
</property>
<!-- 元数据库配置 -->
<property>
<name>javax.jdo.option.ConnectionURL</name>
<value>jdbc:mysql://localhost:3306/hive_debug?createDatabaseIfNotExist=true&characterEncoding=utf8</value>
</property>
<property>
<name>javax.jdo.option.ConnectionUserName</name>
<value>root</value>
</property>
<property>
<name>javax.jdo.option.ConnectionPassword</name>
<value>goodluck</value>
</property>
<property>
<name>javax.jdo.option.ConnectionDriverName</name>
<value>com.mysql.jdbc.Driver</value>
</property>

3.3 初始化元数据库

  (tips:可以提前将scripts/metastore/upgrade/mysql/hive-schema-2.1.0.mysql.sql中的建表语句编码改成utf8,可以避免后续为了解决中文注释、表名、列名再来修改,不过有几个表改成utf8编码会报主键太长的错误,还是要保持latin1编码,可以在改成utf8后运行初始化语句,遇到报错的表时,将那个表的编码再改回latin1编码再执行初始化语句)

Code
1
bin/schematool -dbType mysql -initSchema

4、调试

  目前已经可以开始调试hive源码,采用远程调试的方式。

  1. 将编写并打包好的HiveHook项目的jar包拷到lib目录下,再在conf/hive-site.xml中配置hook类:
    Code
    1
    2
    3
    4
    5
    6
    7
    8
    9
    <property>
    <name>hive.exec.post.hooks</name>
    <value>tech.xxx.HiveHook</value>
    <description>
    Comma-separated list of post-execution hooks to be invoked for each statement.
    A post-execution hook is specified as the name of a Java class which implements the
    org.apache.hadoop.hive.ql.hooks.ExecuteWithHookContext interface.
    </description>
    </property>
  2. 先启动hive metastore:bin/hive --service metastore;
  3. 由于是要调试hive hook,属于hiveserver2的功能,所以以调试模式启动hiveserver2服务:
    Code
    1
    2
    # bin/hive --debug --service hiveserver2
    Listening for transport dt_socket at address: 8000
  4. idea打开cloudera hive项目(之前已经切换到cdh6.3.0分支),在idea项目结构中的Libraries中,添加自己编写的HiveHook项目的Jar包,这样调试时idea才能看到自己的代码;再添加一个Remote Run/Debug Configurations,Host填写为localhost,Port填写为8000,然后点击调试,则idea连接上hivesever2,hiveserver2会继续启动并运行。再打上断点,实践后发现调用post hook的位置在org.apache.hadoop.hive.ql.Driver类1960行的((ExecuteWithHookContext) peh).run(hookContext);处,可以在这里打个断点(当然可以在其他想打的位置打断点,比如先配置一个Hive已实现的Hook类,在run方法打断点);
  5. 启动beeline客户端,开始执行SQL并调试:
    Code
    1
    bin/beeline -u jdbc:hive2://localhost:10000 -n root
      然后执行sql,断点则会触发,即可以在idea中调试hive源码,若想调试metastore或beeline,也可在启动这些功能时加上--debug,仍然使用远程的方式进行调试。

参考链接

文章作者: 0x3E6
文章链接: http://longwang.live/2021/03/23/Hive%E6%BA%90%E7%A0%81%E8%B0%83%E8%AF%95/
版权声明: 本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 0x3E6的博客
打赏
  • 微信
    微信
  • 支付寶
    支付寶