前言
這篇文章默認是已經在云上配置好了 Haoop 集群,因此本文主要是記錄一些可能會出現錯誤的地方。
如果還不會配置 Hadoop 集群,那么可以參考本專欄的另一篇文章:云上配置 Hadoop 集群詳解
另外在進行本文的學習之前也建議先看看該文章,因為一些基本概念這里不會再進行解釋了嗷。
1、本地(windows)配置主機名映射
在使用 Java API 進行遠程訪問之前,要先在本地的 Windows 環境下配置上相應的主機名映射捏。
打開下面路徑,進行文件配置:
C:\Windows\System32\drivers\etc\hosts
打開該文件,可以看到下面的內容:
我們需要在上面追加一行內容,內容格式為:
xxx.xxx.xxx.xxx cloud_host_name
其中前面的 xxx.xxx.xxx.xxx 為你的云服務器的公網 IP 地址,后面的 cloud_host_name 則是你云服務器上的主機名稱,該主機名稱可以在云服務器上鍵入命令:hostname 得知:
因此,假設你的服務器的公網 IP 地址為 111.123.123.123,且云服務器的主機名為 VM-8-4-ubuntu 那么需要追加的內容就是:
111.123.123.123 VM-8-4-ubuntu
2、本地(windows)配置JDK以及Hadoop的環境變量
本地連接云服務器的Hadoop集群時需要配置 Hadoop 的環境變量,否則啟動會報錯,而配置 Hadoop 的環境變量時又依賴 JDK 的環境變量,因此也要配置好 JDK 的本地環境變量。
配置環境變量這個網上教程就太多了,隨便 CSDN 一下都一大把,因此這里不再贅述。
3、云服務器上需要進行的配置
3.1、首先也是需要進行主機名的映射
Linux的主機名配置在根目錄下的 /etc/hosts 文件中,注意需要切換成 root 用戶才有權限進行更改:
/etc/hosts
使用 vim 打開后,如下:
這里要注意,上圖已經是我修改過后的 hosts 文件了,因此如果你和我的不一樣那么也很正常,你只要改成我上面的樣子即可。
那么重點改哪里呢:
眾所周知,在我們購買云服務器時,會有兩個 IP 地址,一個是公網 IP 地址另一個是內網 IP 地址:
形式基本如上圖如所示,那么在云上的 Hadoop 集群中,其內部通信是通過內網進行的,因此我們需要配上類似于剛剛在 Windows 環境上的操作,即在 /etc/hosts 文件中追加下面內容:
內網地址IP 云服務器主機名
如
192.168.88.152 VM-8-4-ubuntu
如果你的云服務器主機名的默認情況下被映射到了別的IP地址(多半是本地環回地址),那么請將其去掉改成上述內容。
總之就是確保你的云服務器主機名所對應的只有一個內網IP地址即可,因為如果有多個的話我們自己設置的內網IP映射主機名的優先級不夠別的映射關系級別高,會讓我們自己設置的不起作用。
3.2、修改Hadoop的配置文件
主要是 Hadoop 文件夾下的下面幾個文件:
1、修改 workers 文件:
vim 打開 workers ,寫入我們的主機名(注意一定是本機的主機名嗷),因為我只有一臺云服務器,所以我只在該文件中寫入一個主機名即可,因此相當于是在構建一個偽分布式 Hadoop 集群:
2、vim 打開 core-site.xml 文件:
在該文件中配置好我們的內部通訊端口,也就是我們的 namenode 主節點,我這唯一一臺的云服務器既是主節點也是從節點,即既是namenode 節點也就是 datanode 節點,因此這里配置主節點用的是本服務器的主機名(注意一定是本機的主機名嗷):
3、vim 打開 hdfs-site.xml 文件
在上文剛剛提過,我這唯一一臺服務器既是主節點也是從節點,因此這里配置數據節點 datanode 時,同樣采用的本機的主機名(注意一定是本機的主機名嗷):
全部弄完這些之后,就可以格式化 namenode 然后啟動 hdfs 集群了。
格式化時不出意外按照上面的配置流程走下來,格式化完后的結果應該如下:
“Shutting down NameNode at VM-8-4ubuntu(也就是你的服務器主機名)/10.0.8.4(也就是你服務器的內網IP地址)”
格式化后如果如上,那么配置應該就沒有問題了。
4、注意云服務器的端口開放問題
因為云服務器的端口默認只開放了幾個,而 hdfs 集群會涉及較多的端口,因此這里根據我的經驗需要開放下面幾個:
首先是我們在之前的配置中所配置的 namenode 的通訊端口:8020,注意這個是我們自己可以配置的:
然后是在集群內部各個節點之間的通訊端口,這是 Hadoop 的 HDFS 默認占用的端口,請注意這幾個端口有無被占用:
把這幾個端口開放了應該連接就沒有問題了。
5、測試
可以使用下面的 Java 代碼進行簡單的測試,也可以讓 GPT 生成一些測試代碼來進行簡單的測試:
@PostMapping("/upload")public ResponseEntity<String> handleFileUpload(@RequestParam("file") MultipartFile file) throws IOException, InterruptedException {//1. 初始化配置對象 需要new出來,用來配置Hadoop的集群節點信息,主要是配置主節點namenodeConfiguration conf = new Configuration();//下面這行代碼告訴Hadoop客戶端使用數據節點(Datanode)的主機名來建立連接,而不是使用IP地址//因為在分布式環境下,節點(包括數據節點)的IP地址可能會發生變化,而主機名通常是穩定的。//因此,通過使用主機名而不是IP地址,可以提高Hadoop集群的可維護性和可靠性conf.set("dfs.client.use.datanode.hostname", "true");//2. 添加配置 (其實就是提供一個key - value)//xxx.xxx.xxx.xxx改成你的公網IP地址嗷FileSystem fileSystem = FileSystem.get(URI.create("hdfs://xxx.xxx.xxx.xxx:8020"),conf,"ubuntu");//4、將前端傳來的文件數據上傳至hdfs/*用MultipartFile的getInputStream方法,獲得輸入流,隨后轉換成Hadoop的FSDataOutputStream輸出流后,就可以將文件上傳到Hadoop最后記得flush和close輸入輸出流*/InputStream inputStream = null;FSDataOutputStream fsDataOutputStream = null;try{inputStream = file.getInputStream();//用戶上傳文件存儲在hdfs中的路徑//截取文件名后綴來分別進行存儲String fileName = file.getOriginalFilename();Path desPath = new Path("/"+fileName);//創建路徑后寫入文件fsDataOutputStream = fileSystem.create(desPath);byte[] b = new byte[4096];int read;while((read=inputStream.read(b)) > 0){fsDataOutputStream.write(b,0,read);}fsDataOutputStream.flush();return ResponseEntity.ok().body("File uploaded to HDFS successfully.");} catch (IOException e){e.printStackTrace();} finally {if (null != inputStream) inputStream.close();if (null != fsDataOutputStream) fsDataOutputStream.close();}//關閉hdfs的連接工具if (fileSystem != null) {fileSystem.close();}return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body("Failed to upload file to HDFS");}
6、其他問題
如果還出現了其他的報錯,那么建議自己反復檢查一下自己的配置以及程序,不然就多多百度,按我的經驗應該是將上面的步驟挨個做完應該就能解決了。
還有一個問題,如果出現了往 HDFS 上寫入文件只能寫入文件名卻無法寫入文件內容的情況時,或者報錯類似于:
org.apache.hadoop.ipc.RemoteException(java.io.IOException): File could only be replicated to 0 nodes instead of minReplication (=1). There are 1 datanode(s) running and 1 node(s) are excluded in this operation.
可以參考下面這篇文章:使用Java API 向 HDFS 中寫入數據報錯解決;