- Hadoop 3實戰指南
- 孫志偉
- 1385字
- 2021-06-15 16:02:46
1.3.1 單元測試
在源碼的根目錄中有個BUILDING.txt文件,其中記錄了編譯Hadoop所需的軟件及一些步驟。由于只是為了進行單元測試和通過斷點的方式調試代碼,因此這里只編譯Hadoop,并沒有生成對應的二進制文件,編譯命令為mvn package -Psrc -DskipTests
。如果要部署Hadoop,還需要將源碼編譯成二進制文件。編譯二進制文件時,需要先安裝一些依賴軟件,具體如下(這里只關注Linux/Mac環境下的編譯步驟,Windows環境下大同小異)。
- JDK 1.8
- Maven 3.3及以上版本
- Protocol Buffer 2.5.0
- CMake 3.1及以上版本
- zlib-devel
- cyrus–sasl-devel
- GCC 4.8.1及以上版本
- openssl-devel
- Linux FUSE 2.6及以上版本
- Jansson
- Doxygen
- Python
- bats
- Node.js
關于它們的具體安裝方式,網上有很多教程,并且較為簡單,故不在此展開。
成功安裝上述依賴軟件之后,執行編譯命令mvn clean package -DskipTests -Pdist, native -Dtar
,正常情況下會在hadoop-dist/target下生成一個Hadoop的二進制tar包。如果沒有成功,也不要慌,執行mvn clean package -DskipTests -Pdist,native -Dtar -X
查看具體是哪兒出錯了,然后再針對性地去解決。我是在Mac環境下編譯的,如果在編譯過程中遇到問題,可以參考我的博客。在Linux環境下,如果依賴軟件都安裝正確,則出錯的概率較小。
將編譯成功的Hadoop代碼按照本節開頭介紹的方式導入IDEA,然后隨便找個測試類執行單元測試,看看是否有異常信息。這里執行TestJob
類,如果成功,則表示源碼閱讀環境已基本部署成功(如果出現有些模塊未識別成Maven項目的情況,可以參考圖1-6進行修改)。
之所以說基本部署成功,是因為還可能會遇到webapps/datanode
或者webapps/hdfs
的異常,錯誤信息為java.io.FileNotFoundException: webapps/datanode not found in CLASSPATH
。如果上述步驟都正常,解決這個問題將非常容易。根據報錯信息可以發現,這是HttpServer2
類拋出的異常,此時只要在代碼處加入一些代碼進行調試即可解決,具體代碼如下:
protected String getWebAppsPath(String appName) throws FileNotFoundException {
URL resourceUrl = null;
// 將webResourceDevLocation賦值為src/main/webapps目錄
File webResourceDevLocation = new File("src/main/webapps", appName);
// 在此處加入代碼,打印出具體的目錄信息
System.out.println(webResourceDevLocation.getAbsolutePath());
// 判斷Web服務器的運行方式
// 當webResourceDevLocation不存在時,運行模式為開發模式
if (webResourceDevLocation.exists()) {
LOG.info("Web server is in development mode. Resources "
+ "will be read from the source tree.");
try {
resourceUrl =
webResourceDevLocation.getParentFile().toURI().toURL();
} catch (MalformedURLException e) {
throw new FileNotFoundException("Mailformed URL whilefinding the
" + "web resource dir:" + e.getMessage());
}
} else {
resourceUrl =
getClass().getClassLoader().getResource("webapps/" + appName);
// 具體的報錯信息是從這里報出的
if (resourceUrl == null) {
throw new FileNotFoundException("webapps/" + appName +
" not found in CLASSPATH");
}
}
String urlString = resourceUrl.toString();
return urlString.substring(0, urlString.lastIndexOf('/'));
}
查看代碼,會發現報錯信息在else
語句塊中。這段代碼的功能是得到Web服務器的路徑,其中有一個if/else
語句塊,用于判斷Web服務器的運行模式。當webResourceDevLocation.exists()
為真,即webResourceDevLocation
對應的目錄存在時,代表運行的是開發模式,進入if
語句塊;不為真時進入else
語句塊,報錯的原因是webResourceDevLocation
對應的目錄不存在。進入else
語句塊后,resourceUrl
未獲取到對應的值,為null
,即判斷條件resourceUrl == null
為真,然后拋出異常。由于這里是在IDEA中運行開發模式,因此只創建webResourceDevLocation
對應的目錄即可。至于具體在哪里創建目錄,只需在if
語句之前加入println
語句,查看Web服務器使用的相對目錄是什么,然后在相對目錄中創建src/main/webapps目錄即可。在實際操作過程中,可能還會報其他異常,也可按照此思路一一解決。
注意:如果導入IDEA的源碼不是通過mvn package -Psrc -DskipTests
進行編譯的,那么執行單元測試時就沒有上面這么順利了。比如會出現找不到proto
類,或者找不到AvroRecord
類的問題,但這些都容易解決,通過對序列化的文件進行編譯,自動生成對應的Java文件,然后將其復制到對應的包目錄即可。比較麻煩的是,有些模塊中找不到另一個模塊的類,這就需要更改當前模塊對其依賴的對應模塊的依賴范圍。例如,導入的代碼是未通過mvn clean package -DskipTests -Pdist,native -Dtar
編譯成功的,運行單元測試時,有可能會報下面的異常信息:
/Users/xx/tmp/hadoop-3.2.0-src/hadoop-common-project/hadoop-auth/src/test/java/org
/apache/hadoop/security/authentication/server/TestKerberosAuthenticationHandler.java
Error:(16, 33) java: 程序包org.apache.hadoop.minikdc不存在
Error:(48, 13) java: 找不到符號
符號: 類 KerberosSecurityTestcase
Error:(81, 5) java: 找不到符號
符號: 方法 getKdc()
位置: 類 org.apache.hadoop.security.authentication.
server.TestKerberosAuthenticationHandler
Error:(186, 5) java: 找不到符號
符號: 方法 getKdc()
位置: 類 org.apache.hadoop.security.authentication.server.
TestKerberosAuthenticationHandler
此時就需要將auth
模塊對minikdc
模塊的依賴范圍改為Compile
或者Provided
,如圖1-7所示。

圖1-7 修改依賴模塊的范圍