大數據開發技術課程報告內容及要求:
報告內容及要求
本報告作爲“大數據開發技術”課程的階段性考試內容,需要獨立完成,可以參考資料。
- 報告內容
在Linux系統上,利用課上所學知識,根據自身機器配置,創建一個僞分佈式Hadoop集羣或完全分佈式Hadoop集羣,並對集羣進行操作。需要在項目實現過程中,體現出通過本課程所學知識。- 報告要求
集羣形式可以根據機器配置在僞分佈式和完全分佈式間進行選擇;
Hadoop集羣及所需組件的安裝和配置需要截圖;
關於Java的目錄:需要自定義名稱,添加學號後綴,比如學號爲18B12345,那麼JAVA_HOME的路徑應該是…/java-18B12345,需要截圖在報告中進行體現;
關於集羣的測試:在Hadoop集羣安裝完成後,需要分別用官方提供的例子和Web UI進行測試,需要截圖在報告中進行體現;
關於集羣的操作:需要分別使用Shell形式和Java API對集羣進行操作並截圖在報告中進行體現,其中:在使用Java API時,Java項目的命名需要具有學號後綴,比如;學號爲18B12345,那麼如果創建的Java項目爲hdfs-api,則實際創建的Java項目爲hadfs-api-18B12345;如果創建的Java代碼文件爲main.java,則實際創建的.java文件爲main_18B12345.java。
一、 項目簡介和實驗環境
本項目主要是建立Hadoop完全分佈式集羣,並進行集羣測試和操作。
主要內容:配置hadoop完全分佈式集羣的前期準備、安裝過程、配置文件、啓動過程、Shell操作、Java API操作。
(本文中的一些文件可能帶有學號後綴,這是課程報告的要求,實際上不必寫後綴)
Linux發行版:ubuntu-18.04.4-desktop-amd64
JDK版本:jdk1.8.0_144
Hadoop版本:hadoop-2.7.2
二、 虛擬機的各項準備工作
創建三臺虛擬機,並完成各項準備工作。
以下的所有準備工作在三臺虛擬機上都要做。由於在準備階段,三臺主機的操作幾乎完全相同,所以在此以第一臺主機hadoop1爲例。所有命令均是在root賬號下運行。
(1) 修改主機名,依次爲hadoop1,hadoop2,hadoop3。
(2) 關閉防火牆
輸入命令ufw disable
,關閉防火牆,重啓後即可生效。
(3) 設置靜態IP, hadoop1主機的設置如下圖所示:
輸入命令ifconfig
,查看一下IP,顯示設置成功:
(4) 配置ssh免密登錄,方便之後用xsync腳本進行集羣分發。
輸入命令vim /etc/hosts
,將主機名與各自IP相對應,如下圖所示:
輸入命令vim /etc/ssh/sshd_config
,找到PermitRootLogin 配置項將原先的PermitRootLogin的prohibit-password修改爲yes:
輸入命令service ssh restart
,重啓ssh。
cd ~
(進入root目錄)
ssh-keygen -t rsa
,再按3次回車
~/.ssh會生成兩個文件:id_rsa(私鑰)、id_rsa.pub(公鑰)
然後將其公鑰加到3個虛擬機目錄下(會生成一個authorized_keys的公鑰,如果已經存在,則在該文件後面將會繼續追加公鑰內容),輸入以下命令:
ssh-copy-id root@hadoop1
ssh-copy-id root@hadoop2
ssh-copy-id root@hadoop3
三臺虛擬機都完成如上操作後,在hadoop1主機上測試是否能以root賬號免密登錄到hadoop2。
輸入命令ssh root@hadoop2
,無需輸入密碼則說明ssh免密登錄配置成功,如下圖所示:
輸入命令exit
退出hadoop2的root賬號,繼續操作。
(5) 編寫集羣分發腳本xsync
輸入命令vim /usr/local/bin/xsync
,編寫內容如下:
#!/bin/bash
if [[ -x $(command -v rsync) ]]; then
echo yes > /dev/null
else
echo no rsync found!
exit 1
fi
#1 獲取輸入參數個數,如果沒有參數,直接退出
pcount=$#
if((pcount==0)); then
echo no args!
exit;
fi
#2 獲取文件名稱
p1=$1
fname=$(basename $p1)
echo fname=$fname
#3 獲取文件絕對路徑
pdir=$(cd -P $(dirname $p1); pwd)
echo pdir=$pdir
#4 獲取當前用戶名稱
user=$(whoami)
#5 循環
for((host=2; host<4; host++)); do
echo --- hadoop$host ---
rsync -rvl $pdir/$fname $user@hadoop$host:$pdir
done
輸入命令chmod +x xsync
,將其提升爲可執行文件的權限。
這個腳本只要寫在hadoop1主機中即可,由它來向其他主機分發文件。
三、 安裝JDK並配置環境變量
在hadoop1主機中安裝JDK並配置相應文件,同時用xsync同步文件到其他主機。
輸入命令tar -zxvf jdk-8u144-linux-x64.tar.gz
解壓得到jdk1.8.0_144目錄,將其改名爲jdk1.8.0_144-2018214184。
輸入命令xsync jdk1.8.0_144-2018214184
,將其分發到其他主機上。
輸入命令vim /etc/profile.d/java.sh
,配置環境變量:
輸入命令xsync /etc/profile.d/java.sh
,將其分發到其他主機上:
輸入命令source /etc/profile
使環境變量生效。
最後,輸入命令java -version
,檢驗是否配置成功,如圖所示,說明java已經配置成功:
四、 安裝Hadoop並配置環境變量
在hadoop1主機中安裝Hadoop並配置相應文件,同時用xsync同步文件到其他主機。
輸入命令tar -zxvf hadoop-2.7.2.tar.gz
解壓得到hadoop-2.7.2目錄。
輸入命令xsync hadoop-2.7.2
,將其分發到其他主機上。
輸入命令vim /etc/profile.d/hadoop.sh
,配置環境變量:
輸入命令xsync /etc/profile.d/hadoop.sh
,將其分發到其他主機上:
輸入命令source /etc/profile
使環境變量生效。
最後,再輸入命令hadoop
,檢驗是否配置成功,如圖所示,說明Hadoop已經配置成功:
五、 配置Hadoop完全分佈式集羣
集羣部署規劃:
爲了能羣啓集羣,還需要配置/opt/hadoop-2.7.2/etc/hadoop目錄下的一些文件。
vim hadoop-env.sh
,加入JAVA_HOME:
vim yarn-env.sh
,加入JAVA_HOME:
vim mapred-env.sh
,加入JAVA_HOME:
vim core-site.xml
vim hdfs-site.xml
vim yarn-site.xml
,注意是在兩個<configuration>之間添加,其他內容不要改變:
vim mapred-site.xml
vim slaves
輸入命令xsync /opt/hadoop-2.7.2/etc/hadoop
,將配置文件同步到所有節點:
六、 啓動Hadoop完全分佈式集羣
首先進入到 /opt/hadoop-2.7.2 目錄下,jps確認節點都已關閉後,
輸入命令rm -r logs data
和bin/hdfs namenode -format
,格式化NameNode。
(三臺虛擬機都要執行該操作)
羣啓集羣,先在規劃的NameNode(hadoop1主機)執行命令sbin/start-dfs.sh
,如下圖:
顯示hadoop1主機上啓動NameNode和DataNode成功。
繼續檢查hadoop2和hadoop3上是否啓動成功,若成功則繼續操作。
然後在規劃的ResourceManager(hadoop2主機)執行命令sbin/start-yarn.sh
,如下圖:
然後輸入jps
命令檢查三臺主機是否都啓動成功。
hadoop1主機:
hadoop2主機:
hadoop3主機:
三個主機的jps表明,按照規劃羣啓hadoop集羣成功。
Web UI能正常訪問hadoop1:50070,如下圖:
Web UI能正常訪問hadoop2:8088,如下圖:
Web UI能正常訪問hadoop3:50090,如下圖:
七、 Hadoop完全分佈式集羣的Shell操作
(1) 在HDFS上創建目錄:hadoop fs -mkdir -p /tmp/test
Web UI顯示在HDFS上創建目錄成功,如下圖:
(2) 從本地系統中拷貝文件到HDFS路徑中,輸入以下命令:
touch /tmp/zhangsan.txt
echo “I am zhangsan” > /tmp/zhangsan.txt
hadoop fs -copyFromLocal /tmp/zhangsan.txt /tmp/test
Web UI顯示從本地拷貝文件到HDFS成功,如下圖:
(3) 從HDFS上拷貝文件到本地,輸入以下命令:
rm /tmp/zhangsan.txt
hadoop fs -copyToLocal /tmp/test/zhangsan.txt /tmp
cat /tmp/zhangsan.txt
刪除了本地文件,又得到了一模一樣的文件,說明從HDFS上拷貝文件到本地成功,運行結果如圖:
(4) 將文件從HDFS的一個路徑拷貝到另一個路徑:hadoop fs -cp /tmp/test/zhangsan.txt /
Web UI顯示文件從HDFS的一個路徑拷貝到另一個路徑成功,如下圖:
(5) 刪除HDFS的文件:hadoop fs -rm /zhangsan.txt
Web UI顯示在HDFS上之前拷貝得到的/zhangsan.txt已被成功刪除。
(6) 統計文件的大小信息:hadoop fs -du -h /tmp/test/zhangsan.txt
Web UI上顯示的文件大小和終端顯示的文件大小相同,都是20B,如下圖:
(7) 運行官方案例中的WordCount程序
輸入命令hadoop jar share/hadoop/mapreduce/hadoop-mapreduce-examples-2.7.2.jar wordcount /tmp/test/zhangsan.txt /tmp/output
(這裏注意在HDFS上/tmp/output事先不能存在,否則無法運行WordCount)
運行過程的後幾十行如下:
輸入命令hadoop fs -cat /tmp/output/p*
,查看生成的文件,Web UI顯示生成了/tmp/output/part-r-00000,查看該文件,顯示是WordCount運行的結果,如下圖:
八、 Hadoop完全分佈式集羣的Java API操作
先安裝並配置好maven(maven安裝步驟和jdk類似),輸入命令mvn -version
,如下圖顯示maven已安裝成功:
輸入命令vim ${MAVEN_HOME}/conf/settings.xml
,更換${MAVEN_HOME}/conf/settings.xml文件中的mirror爲阿里雲:
輸入命令mvn archetype:generate -DgroupId=com.root
,顯示創建目錄hdfs-mkdir-2018214184成功,如下圖:
進入hdfs-mkdir-2018214184目錄,輸入以下命令:
mvn clean
mvn package
tree
結果如圖所示,編譯生成了target目錄:
輸入命令java -cp target/hdfs-mkdir-2018214184-1.0-SNAPSHOT.jar com.root.App
如圖所示,能成功運行Java程序,輸出Hello World
輸入命令vim pom.xml
,導入依賴和插件:
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>RELEASE</version>
</dependency>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-core</artifactId>
<version>2.8.2</version>
</dependency>
<dependency>
<groupId>org.apache.hadoop</groupId>
<artifactId>hadoop-common</artifactId>
<version>${hadoop.version}</version>
</dependency>
<dependency>
<groupId>org.apache.hadoop</groupId>
<artifactId>hadoop-client</artifactId>
<version>${hadoop.version}</version>
</dependency>
<dependency>
<groupId>org.apache.hadoop</groupId>
<artifactId>hadoop-hdfs</artifactId>
<version>${hadoop.version}</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>2.3.2</version>
<configuration>
<archive>
<manifest>
<addClasspath>true</addClasspath>
<classpathPrefix>lib/</classpathPrefix>
<mainClass>com.root</mainClass>
</manifest>
</archive>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
<executions>
<execution>
<id>copy</id>
<phase>package</phase>
<goals>
<goal>copy-dependencies</goal>
</goals>
<configuration>
<outputDirectory>
${project.build.directory}/lib
</outputDirectory>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
再次輸入命令:
mvn clean
mvn package
java -cp target/hdfs-mkdir-1.0-SNAPSHOT.jar com.root.App
運行結果如圖,說明導入依賴和插件後,程序能正常運行。
接下來可以自己編寫Java程序,通過Java API操作HDFS。
(1) 調用Java API,在HDFS上創建目錄。
輸入命令vim /opt/workspace/hdfs-mkdir-2018214184/src/main/java/com/root/Mkdir_2018214184.java
,編寫源碼如下:
package com.root;
import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.FileSystem;
import org.apache.hadoop.fs.Path;
public class Mkdir_2018214184
{
public static void main( String[] args ) throws IOException, Exception, URISyntaxException
{
Configuration conf = new Configuration();
//1 獲取hdfs客戶端對象
FileSystem fs = FileSystem.get(new URI("hdfs://hadoop1:9000"), conf, "root");
//2 在hdfs上創建路徑
fs.mkdirs(new Path("/0x00/usr"));
//3 關閉資源
fs.close();
System.out.println( "HDFS mkdir!" );
}
}
輸入命令:
mvn clean
mvn package
java -cp target/hdfs-mkdir-1.0-SNAPSHOT.jar com.root.Mkdir_2018214184
在Web UI上可以看到成功創建0x00目錄,如下圖:
(2) 調用Java API,從本地拷貝文件到HDFS。
輸入命令vim /opt/workspace/hdfs-mkdir-2018214184/src/main/java/com/root/CopyFromLocal_2018214184.java
,編寫源碼如下:
package com.root;
import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.FileSystem;
import org.apache.hadoop.fs.Path;
public class CopyFromLocal_2018214184
{
public static void main( String[] args ) throws IOException, Exception, URISyntaxException
{
Configuration conf = new Configuration();
//1 獲取hdfs客戶端對象
FileSystem fs = FileSystem.get(new URI("hdfs://hadoop1:9000"), conf, "root");
//2 將本地文件上傳到hdfs上
fs.copyFromLocalFile(new Path("/tmp/java-api-2018214184.txt"), new Path("/java-api-2018214184.txt"));
//3 關閉資源
fs.close();
System.out.println( "HDFS copy from local!" );
}
}
輸入命令:
touch /tmp/java-api-2018214184.txt
echo This is a java-api test > /tmp/java-api-2018214184.txt
mvn clean
mvn package
java -cp target/hdfs-mkdir-1.0-SNAPSHOT.jar com.root.CopyFromLocal_2018214184
在Web UI上可以看到從本地拷貝java-api-2018214184.txt到HDFS成功,如下圖:
(3) 調用Java API,從HDFS拷貝文件到本地。
輸入命令vim /opt/workspace/hdfs-mkdir-2018214184/src/main/java/com/root/CopyToLocal_2018214184.java
,編寫源碼如下:
package com.root;
import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.FileSystem;
import org.apache.hadoop.fs.Path;
public class CopyToLocal_2018214184
{
public static void main( String[] args ) throws IOException, Exception, URISyntaxException
{
Configuration conf = new Configuration();
//1 獲取hdfs客戶端對象
FileSystem fs = FileSystem.get(new URI("hdfs://hadoop1:9000"), conf, "root");
//2 下載操作
fs.copyToLocalFile(new Path("/java-api-2018214184.txt"), new Path("/tmp/java-api-2018214184.txt"));
//3 關閉資源
fs.close();
System.out.println( "HDFS copy to local!" );
}
}
輸入命令:
mvn clean
mvn package
rm /tmp/java-api-2018214184.txt
java -cp target/hdfs-mkdir-1.0-SNAPSHOT.jar com.root.CopyToLocal_2018214184
cat /tmp/java-api-2018214184.txt
刪除本地文件,再下載,cat命令顯示能打開剛纔從HDFS下載的文件,並且內容一致,如下圖:
(4) 調用Java API,刪除HDFS上的文件。
輸入命令vim /opt/workspace/hdfs-mkdir-2018214184/src/main/java/com/root/Delete_2018214184.java
,編寫源碼如下:
package com.root;
import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.FileSystem;
import org.apache.hadoop.fs.Path;
public class Delete_2018214184
{
public static void main( String[] args ) throws IOException, Exception, URISyntaxException
{
Configuration conf = new Configuration();
//1 獲取hdfs客戶端對象
FileSystem fs = FileSystem.get(new URI("hdfs://hadoop1:9000"), conf, "root");
//2 文件刪除
fs.delete(new Path("/0x00"), true);
//3 關閉資源
fs.close();
System.out.println( "HDFS delete!" );
}
}
輸入命令:
mvn clean
mvn package
java -cp target/hdfs-mkdir-1.0-SNAPSHOT.jar com.root.Delete_2018214184
在Web UI上顯示刪除0x00目錄成功,如下圖:
(5) 調用Java API,重命名HDFS上的文件。
輸入命令vim /opt/workspace/hdfs-mkdir-2018214184/src/main/java/com/root/Rename_2018214184.java
,編寫源碼如下:
package com.root;
import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.FileSystem;
import org.apache.hadoop.fs.Path;
public class Rename_2018214184
{
public static void main( String[] args ) throws IOException, Exception, URISyntaxException
{
Configuration conf = new Configuration();
//1 獲取hdfs客戶端對象
FileSystem fs = FileSystem.get(new URI("hdfs://hadoop1:9000"), conf, "root");
//2 文件更名
fs.rename(new Path("/java-api-2018214184.txt"), new Path("/rename-2018214184.txt"));
//3 關閉資源
fs.close();
System.out.println( "HDFS rename!" );
}
}
輸入命令:
mvn clean
mvn package
java -cp target/hdfs-mkdir-1.0-SNAPSHOT.jar com.root.Rename_2018214184
在Web UI上顯示重命名文件成功,如下圖:
(6) 調用Java API,查看HDFS根目錄下所有文件的詳細信息。
輸入命令vim /opt/workspace/hdfs-mkdir-2018214184/src/main/java/com/root/ListFiles_2018214184.java
,編寫源碼如下:
import java.net.URI;
import java.net.URISyntaxException;
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.FileSystem;
import org.apache.hadoop.fs.Path;
import org.apache.hadoop.fs.RemoteIterator;
import org.apache.hadoop.fs.LocatedFileStatus;
import org.apache.hadoop.fs.BlockLocation;
public class ListFiles_2018214184
{
public static void main( String[] args ) throws IOException, Exception, URISyntaxException
{
Configuration conf = new Configuration();
//1 獲取hdfs客戶端對象
FileSystem fs = FileSystem.get(new URI("hdfs://hadoop1:9000"), conf, "root");
//2 查看文件詳情
RemoteIterator<LocatedFileStatus> listFiles = fs.listFiles(new Path("/"), true);
while (listFiles.hasNext())
{
LocatedFileStatus fileStatus = listFiles.next();
// 查看文件名稱、權限、長度、塊信息
System.out.println(fileStatus.getPath().getName());
System.out.println(fileStatus.getPermission());
System.out.println(fileStatus.getLen());
BlockLocation[] blockLocations = fileStatus.getBlockLocations();
for (BlockLocation blockLocation: blockLocations)
{
String[] hosts = blockLocation.getHosts();
for (String host: hosts)
{
System.out.println(host);
}
}
System.out.println( "----------" );
}
//3 關閉資源
fs.close();
System.out.println( "HDFS list files" );
}
}
輸入命令:
mvn clean
mvn package
java -cp target/hdfs-mkdir-1.0-SNAPSHOT.jar com.root.ListFiles_2018214184
列出了很多文件的詳細信息,可以看到zhangsan.txt有三個副本,大小爲20B,與之前Web UI顯示的結果相同,如下圖:
(7) 調用Java API,查看HDFS根目錄下的各個文件的類型(文件或文件夾)。
輸入命令vim /opt/workspace/hdfs-mkdir-2018214184/src/main/java/com/root/ListStatus_2018214184.java
,編寫源碼如下:
package com.root;
import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.FileSystem;
import org.apache.hadoop.fs.Path;
import org.apache.hadoop.fs.RemoteIterator;
import org.apache.hadoop.fs.LocatedFileStatus;
import org.apache.hadoop.fs.FileStatus;
import org.apache.hadoop.fs.BlockLocation;
public class ListStatus_2018214184
{
public static void main( String[] args ) throws IOException, Exception, URISyntaxException
{
Configuration conf = new Configuration();
//1 獲取hdfs客戶端對象
FileSystem fs = FileSystem.get(new URI("hdfs://hadoop1:9000"), conf, "root");
//2 判斷操作
FileStatus[] listStatus = fs.listStatus(new Path("/"));
for (FileStatus fileStatus: listStatus)
{
if (fileStatus.isFile())
{
// 文件
System.out.println("This is file: "+fileStatus.getPath().getName());
}
else
{
// 文件夾(目錄)
System.out.println("This is directory: "+fileStatus.getPath().getName());
}
}
//3 關閉資源
fs.close();
System.out.println( "HDFS list status!" );
}
}
輸入命令:
mvn clean
mvn package
java -cp target/hdfs-mkdir-1.0-SNAPSHOT.jar com.root.ListStatus_2018214184
可以看到rename-2018214184.txt是文件,tmp是文件夾(目錄),與Web UI顯示的結果相同,如下圖:
九、 階段總結
這次的大數據開發技術課程報告,主要記錄了配置hadoop完全分佈式集羣的前期準備、安裝過程、配置文件、啓動過程、Shell操作、Java API操作。
配合教學視頻自己全部操作了一遍,可以感覺到這門課的內容是很豐富的。在操作過程中難免會出現很多問題,遇到問題不要怕,找到日誌記錄上的Error和Fatal信息,一般來說出現錯誤的情況大多是配置文件的問題,按照錯誤信息去改即可。
在課程報告中,有很多實用的知識點,比如xsync腳本實現多個節點的文件同步,ssh免密登錄,以及Java API操作HDFS等等。其中xsync腳本實現了對rsync命令的二次封裝, Java API則實現了由Java程序操作HDFS的各種功能,而Java程序的源碼都是可以自己寫的,也可以調用官方的庫文件,可擴展性很強。
用編寫好的程序代替手工繁瑣的工作,實現各種想要的功能,這正是課程實踐的樂趣所在,而解決一個個問題,創建出自己獨特的項目,也是一件有成就感的事。希望在下次課程實踐中能學到更多實用的知識,實現更加有意思的功能。
花了兩天時間,終於寫完了這篇課程報告,你現在看到的這篇文章是將近30頁的Word文檔。