天天看點

如何 debug 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
           

複制

如何 debug Hive 源碼,知其然知其是以然

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 [email protected]: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
           

複制

如何 debug Hive 源碼,知其然知其是以然

image-20210116161131896

編譯完之後,在 packaging 包中會生成一個二進制包,這個包可以在伺服器上運作的

如何 debug Hive 源碼,知其然知其是以然

image-20210117203723039

四、Hive 環境搭建

上傳包并且解壓縮,重命名解壓縮後的目錄為 hive

如何 debug 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
           

複制

如何 debug Hive 源碼,知其然知其是以然

image-20210117204324201

伺服器顯示在本機的 8000 端口等待連接配接

然後我們在 Idea 中配置一個遠端 debug

如何 debug Hive 源碼,知其然知其是以然

image-20210117204425904

點選 Debug 按鈕,就可以 Debug了。

主要是 Debug 一下 CLIDriver 的 main 方法,裡面有一個 run 方法

如何 debug Hive 源碼,知其然知其是以然

image-20210117205731396

追蹤到後面的源碼,可以發現一直在等待使用者的輸入,每次輸入之後,都會用 processLine 方法處理

如何 debug Hive 源碼,知其然知其是以然

image-20210117205824507

processLine 也就是 Hive 執行 SQL 主要邏輯了,熟讀這塊代碼,便可看到 Hive 的核心邏輯。

具體的邏輯正在研究中,有成果了會發文,敬請期待。