[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_HOMECode
1
export JAVA_HOME=/usr/lib/jvm/java-8-openjdk-amd64
- core-site.xmlCode
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.xmlCode
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.xmlCode
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.xmlCode
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 配置环境变量
Code1
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/bin2.3 格式化namenode
Code1
$HADOOP_HOME/sbin/hdfs namenode -format
2.4 启动hdoop
确保yarn的ResourceManager、NodeManager,hdfs的NameNode、SecondaryNameNode、DataNode服务启动即可。Code1
$HADOOP_HOME/sbin/start-all.sh
3、编译Hive
3.1 编译
克隆cloudera/hive仓库,切换到cdh6.3.0分支(当前使用的版本),可以设置一下项目根目录下的pom.xml中的仓库地址,换成比较快的仓库,然后在项目根目录下执行mvn clean package -DskipTests -Pdist
,构建可发布的tar包。运行完后生成的文件在packagine [hive-package]
模块中,如下为相关文件列表:Code1
2
3
4drwxrwxrwx 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.gz3.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
中修改或添加一些必要的配置:
1 | <property> |
3.3 初始化元数据库
(tips:可以提前将scripts/metastore/upgrade/mysql/hive-schema-2.1.0.mysql.sql
中的建表语句编码改成utf8,可以避免后续为了解决中文注释、表名、列名再来修改,不过有几个表改成utf8编码会报主键太长的错误,还是要保持latin1编码,可以在改成utf8后运行初始化语句,遇到报错的表时,将那个表的编码再改回latin1编码再执行初始化语句)
1 | bin/schematool -dbType mysql -initSchema |
4、调试
目前已经可以开始调试hive源码,采用远程调试的方式。
- 将编写并打包好的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> - 先启动hive metastore:
bin/hive --service metastore
; - 由于是要调试hive hook,属于hiveserver2的功能,所以以调试模式启动hiveserver2服务:Code
1
2# bin/hive --debug --service hiveserver2
Listening for transport dt_socket at address: 8000 - 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方法打断点); - 启动beeline客户端,开始执行SQL并调试:然后执行sql,断点则会触发,即可以在idea中调试hive源码,若想调试metastore或beeline,也可在启动这些功能时加上Code
1
bin/beeline -u jdbc:hive2://localhost:10000 -n root
--debug
,仍然使用远程的方式进行调试。