最近在出差,客戶現場的 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 [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
複制
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&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 的核心邏輯。
具體的邏輯正在研究中,有成果了會發文,敬請期待。