Hive执行流程源码解析

最近在出差,客户现场的 HiveServer 在很长时间内不可用,查看 CM 的监控发现,HiveServer 的内存在某一时刻暴涨,同时 JVM 开始 GC,每次 GC 长达 1 分钟,导致很长时间内,整个 HiveServer 不可用。

查看 HiveServer 日志发现,在那个内存暴涨的时间点,执行了一个 select count(1) from table 的 SQL,这个表有 2 万多分区,而且执行了很多次。

但是我始终无法解释,这样简单的 SQL 执行过程是什么,MapReduce 的什么阶段产生的什么对象占用了 HiveServer 的内存。

(导致被客户鄙视了,囧!)

这个问题其实也很好解决,两条路可以齐头并进:

  • 一条路是把 HiveServer 那个时候的内存 dump 下来,分析一下里面究竟是什么东西;但这样无法看到具体执行流程是什么;
  • 第二条路是下载 Hive 源码,直接 Debug 执行过程,弄清楚了之后,就可以解释中间的过程了。

本文正是为 debug hive 源码准备的环境。

一、服务器环境准备

我是用的 virtual box,centos 7

配置 hosts

安装必要的包:

yum install -y which dos2unix

二、Hadoop Standalone 环境搭建

下载一个 hadoop 发布包,地址是:

https://archive.apache.org/dist/hadoop/common/hadoop-2.7.7/

下载这个文件

hadoop-2.7.7.tar.gz

上传到服务器,并解压缩到本地,我的目录是 /my2/hadoop

配置环境变量

vi /etc/profile

追加

JAVA_HOME=/usr/local/jdk1.8.0_131
HADOOP_HOME=/my2/hadoop

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

刷新环境变量

source /etc/profile

修改配置文件

(1)修改 etc/hadoop/hadoop-env.sh 文件

java 路径为上文构建 jdk 镜像中,Dockerfile 中写的路径

export JAVA_HOME=/usr/local/jdk1.8

(2)修改 etc/hadoop/core-site.xml 文件

这里有个写死的项是主机名,我的是 hadoop001,修改成你自己的

<configuration>
       <property>
               <name>fs.defaultFS</name>
               <value>hdfs://hadoop001:9000</value>
       </property>
       <property>
               <name>hadoop.tmp.dir</name>
               <value>/usr/local/hadoop/tmp</value>
       </property>
        <property>
                <name>fs.trash.interval</name>
                <value>1440</value>
       </property>
</configuration>

(3)修改 etc/hadoop/hdfs-site.xml 文件

<configuration>
   <property>
       <name>dfs.replication</name>
       <value>1</value>
   </property>
   <property>
       <name>dfs.permissions</name>
       <value>false</value>
   </property>
</configuration>

(4)修改 etc/hadoop/yarn-site.xml 文件

<configuration>
       <property>
               <name>yarn.nodemanager.aux-services</name>
               <value>mapreduce_shuffle</value>
       </property>
       <property>
               <name>yarn.log-aggregation-enable</name>
               <value>true</value>
       </property>
</configuration>

(5)修改 etc/hadoop/mapred-site.xml.template 文件

重命名为 mapred-site.xml ,内容修改如下:

<configuration>
   <property>
       <name>mapreduce.framework.name</name>
       <value>yarn</value>
   </property>
</configuration>

启动 hadoop

格式化 hdfs

chmod -R 775 /my2/hadoop/*
/my2/hadoop/bin/hdfs namenode -format

启动 standalone 模式

/my2/hadoop/sbin/start-all.sh

查看是否启动成功

jps
image-20210117203128158

三、编译 Hive 源码

从 gitee 上 clone Hive 的代码

https://gitee.com/apache/hive

注意克隆之前一定要设置一下 git 换行符是否自动转换的

表示检出时 (clone),不自动转换为 crlf (windows)格式,以免最终打出来的包,脚本的格式都是 windows 格式的,无法运行。

git config --global core.autocrlf input

clone 到本地

git clone git@gitee.com:apache/hive.git

切换到 2.1.0 分支

git checkout rel/release-2.1.0

本地需要先编译一下整个工程,因为有些代码是用 antlr 自动生成的,编译之后,会产生对应的类。

这里必须指定 profile 为 hadoop-2 来支持 hadoop 2.x 版本

mvn clean package -Phadoop-2 -DskipTests -Pdist
image-20210116161131896

编译完之后,在 packaging 包中会生成一个二进制包,这个包可以在服务器上运行的

image-20210117203723039

四、Hive 环境搭建

上传包并且解压缩,重命名解压缩后的目录为 hive

image-20210116222020761

使用 docker 启动 mysql (使用 Docker 比较方便,你也可以使用你自己的 Mysql)

docker run -d -it --name mysql -p 3306:3306 -e MYSQL_ROOT_PASSWORD=debezium -e MYSQL_USER=mysqluser -e MYSQL_PASSWORD=mysqlpw debezium/example-mysql

配置 hive-site.xml

cd /my2/hive/conf
cp hive-default.xml.template hive-site.xml
vi hive-site.xml

打开发现里面每一行都有一个 ^M 字符,这是 windows 换行符导致的,使用 dos2unix 替换即可

dos2unix hive-site.xml

编辑 hive-site.xml

vi hive-site.xml

按 Esc,输入 /Connection (搜索 Connection),把搜索到的这几个 key 的值,替换成下面的

<property>
   <name>javax.jdo.option.ConnectionUserName</name>
   <value>root</value>
</property>
<property>
   <name>javax.jdo.option.ConnectionPassword</name>
   <value>debezium</value>
</property>
<property>
   <name>javax.jdo.option.ConnectionURL</name>
   <value>jdbc:mysql://192.168.56.10:3306/hive?createDatabaseIfNotExist=true&amp;useSSL=false</value>
</property>
<property>
   <name>javax.jdo.option.ConnectionDriverName</name>
   <value>com.mysql.jdbc.Driver</value>
</property>

复制 mysql 驱动到 hive 的 lib 目录下

初始化 metastore 的数据库

/my2/hive/bin/schematool -dbType mysql -initSchema

接着 vi hive-site.xml,搜索 /user.name

把 {system:java.io.tmpdir} 改成 /home/hadoop/hive/tmp/

把 {system:user.name} 改成 {user.name}

启动 Hive 命令行即可

搜索 Connection

五、导入到 Idea 中 Debug

然后把源码导入 IDEA 中,等待 IDEA 完成。

这里的 Debug 很简单,我们在服务器上远程 Debug。

首先在服务器上执行

hive --debug
image-20210117204324201

服务器显示在本机的 8000 端口等待连接

然后我们在 Idea 中配置一个远程 debug

image-20210117204425904

点击 Debug 按钮,就可以 Debug了。

主要是 Debug 一下 CLIDriver 的 main 方法,里面有一个 run 方法

image-20210117205731396

追踪到后面的源码,可以发现一直在等待用户的输入,每次输入之后,都会用 processLine 方法处理

image-20210117205824507

processLine 也就是 Hive 执行 SQL 主要逻辑了,熟读这块代码,便可看到 Hive 的核心逻辑。

下次我们再探讨。

原创文章,作者:kk,如若转载,请注明出处:http://www.wangkai123.com/18/

(0)
上一篇 2022-06-18 11:24
下一篇 2022-06-18 13:31

相关推荐

  • vim 的使用

    一、命令模式中最常用的一些命令 dd 删除(剪切)光标所在行 5dd 删除(剪切)从光标处开始的5行 yy 复制光标所在的整行 5yy 复制从光标处开始的5行 n 显示搜索命令定位…

    Linux 2022-07-03
  • Flink-Clients 模块源码阅读

    本文大纲 一、Flink 官方文档这么全面,为什么还要读 Flink 源码 读文档和读源码的目的是不一样的,就拿 Apache Flink 这个项目来说,如果你想知道 Flink …

    Flink 2022-06-19
  • Flink 源码阅读准备之 – Java8 异步编程

    阅读 Flink 源码前必会的知识 Java8 异步编程 本文大纲速看 一、异步编程 通常来说,程序都是顺序执行,同一时刻只会发生一件事情。如果一个函数依赖于另一个函数的结果,它只…

    Flink 2022-06-19
  • Flink 异步编程模型介绍

    本次我们来实现一个支持百万并发连接数的采集服务器,并且找到异步+ NIO 的编程方式和实时流模型的那些千丝万缕的联系。 一、需求说明 简单的需求功能如下: 数据采集是一个 web …

    Flink 2022-06-19
  • Flink 异步 I/O 解析

    一、简介 我们知道 flink 对于外部数据源的操作可以通过自带的连接器,或者自定义 sink 和 source 实现数据的交互。 那么为啥还需要异步 IO 呢?那时因为对于实时处…

    Flink 2022-06-19
  • Flink Sql 核心概念剖析

    本次,我们从 0 开始逐步剖析 Flink SQL 的来龙去脉以及核心概念,并附带完整的示例程序,希望对大家有帮助! 本文大纲 一、快速体验 Flink SQL 为了快速搭建环境体…

    Flink 2022-06-19
  • Flink 用户代码如何生成 StreamGraph(下)

    九、一小段源码 上次说到了所有的算子都会转化成 transformation ,并放到一个 List 列表中,那么今天我们开始遍历这个列表,来生成 StreamGraph。 打开这…

    Flink 2022-06-19
  • Flink 源码阅读准备之 – Apache Commons Cli

    一、介绍一下 Apache Commons Cli,有一个感官的认识 我们在使用一些开源项目时,会敲一些命令,有简单的,比如 hadoop version;有复杂的,比如 flin…

    Flink 2022-06-19
  • Flink-Clients 源码阅读(2)

    一、我们本次的目的是什么? 这次我们的目的是,在本地的 IDEA 中去 debug flink-clients 代码,然后远程提交给 flink standalone 集群上去执行…

    Flink 2022-06-19
  • Flink 用户代码如何生成 StreamGraph (1)

    Flink 是如何将你写的代码生成 StreamGraph 的(1) 一、絮叨两句 新的一年又来了,不知道大家有没有立几个每年都完不成的 FLAG ? 反正我立了,我今年给自己立的…

    Flink 2022-06-19

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注