hadoop搭建與eclipse開發環境設置

 發現粘貼上來,圖片不見了,格式也變樣了。

所以給個完整的DOS文檔下載地址:

CSDN:http://download.csdn.net/source/3451748 

百度文庫:http://wenku.baidu.com/view/91a5d3c489eb172ded63b797.html

 

hadoop搭建與eclipse開發環境設置

1.    前言
1.1 目標

目的很簡單,爲進行研究與學習,部署一個hadoop運行環境,並搭建一個hadoop開發與測試環境。

具體目標是:

ü  在ubuntu系統上部署hadoop

ü  在windows 上能夠使用eclipse連接ubuntu系統上部署的hadoop進行開發與測試


1.2 軟硬件要求

硬件要求:

三臺普通PC。

當然使用虛擬機也可以,本環境搭建也是VMWare6.5虛擬機上進行的。

軟件要求:

操作系統:ubuntu 11.04 server。

Hadoop版本: hadoop-0.20.2

Eclipse版本:3.3.2

Java版本:1.6.0_26(必須1.6以上)

 

 

注意:

Hadoop版本和Eclipse版本請嚴格按照要求。

現在的hadoop最新版本是hadoop-0.20.203,我在windows上使用eclipse(包括3.6版本和3.3.2版本)連接ubuntu上的hadoop-0.20.203環境一直沒有成功。但是開發測試程序是沒有問題的,不過需要注意權限問題。

    如果要減少權限問題的發生,可以這樣做:ubuntu上運行hadoop的用戶與windows上的用戶一樣。


1.3 環境拓撲圖

主機名

Hadoop角色

Hadoop jps命令結果

Hadoop用戶

Hadoop安裝目錄

ubuntu

Master

slaves

NameNode

DataNode

JobTracker

TaskTracker

SecondaryNameNode

創建相同的用戶的組名:hadoop。

安裝hadoop-0.20.2時使用hadoop用戶,並且hadoop的文件夾歸屬也是hadoop:hadoop

/opt/hadoop

Ubuntu1

slaves

DataNode

TaskTracker

Ubuntu2

slaves

DataNode

TaskTracker

Windows

開發測試環境

安裝了jdk與eclipse,本身不需要安裝hadoop,但是需要hadoop安裝包下面的jar包。

 注意:ubuntu既是NameNode又是DataNode,同時也是JobTracker。

 


 


2.    Ubuntu 安裝

安裝ubuntu11.04 server系統,具體略。

我是先在虛擬機上安裝一個操作系統,然後把hadoop也安裝配置好了,再克隆二份,然後把主機名與IP修改,再進行主機之間的SSH配置。

 

如果僅作爲hadoop的運行與開發環境,不需要安裝太多的系統與網絡服務,或者在需要的時候通過apt-get install進行安裝。不過SSH服務是必須的。


3.    Hadoop 安裝

以下的hadoop安裝以主機ubuntu下進行安裝爲例。

 


3.1 下載安裝jdk1.6

安裝版本是:jdk-6u26-linux-i586.bin,我把它安裝拷貝到:/opt/jdk1.6.0_26

 


3.2 下載解壓hadoop

安裝包是:hadoop-0.20.2.tar.gz。

$ tar  –zxvf  hadoop-0.20.2.tar.gz

$ mv  hadoop-0.20.2  /opt/hadoop

 


3.3 修改系統環境配置文件

         切換爲根用戶。

 

l  修改環境配置文件/etc/profile,加入:

export JAVA_HOME=/opt/jdk1.6.0_26

export JRE_HOME=/opt/jdk1.6.0_26/jre

export CLASSPATH=.:$JAVA_HOME/lib:$JRE_HOME/lib:$CLASSPATH

export PATH=$JAVA_HOME/bin:$JRE_HOME/bin:$PATH

export HADOOP_HOME=/opt/hadoop

export PATH=$HADOOP_HOME/bin:$PATH

 

l  修改地址解析文件/etc/hosts,加入

192.168.69.231  ubuntu

192.168.69.232  ubuntu1

192.168.69.233  ubuntu2

 


3.4 修改hadoop的配置文件

切換爲hadoop用戶。

 

l  修改hadoop目錄下的conf/hadoop-env.sh文件

加入java的安裝根路徑:

export JAVA_HOME=/opt/jdk1.6.0_26

 

l  把hadoop目錄下的conf/core-site.xml文件修改成如下:

<?xml version="1.0"?>

<?xml-stylesheet type="text/xsl" href="configuration.xsl"?>

 

<!-- Put site-specific property overrides in this file. -->

 

<configuration>

<property>

  <name>hadoop.tmp.dir</name>

  <value>/hadoop</value>

  <description>A base for other temporary directories.</description>

</property>

 

<property>

  <name>fs.default.name</name>

  <value>hdfs://ubuntu:9000</value>

  <description>The name of the default file system.  A URI whose

  scheme and authority determine the FileSystem implementation.  The

  uri's scheme determines the config property (fs.SCHEME.impl) naming

  the FileSystem implementation class.  The uri's authority is used to

  determine the host, port, etc. for a filesystem.</description>

</property>

 

<property>

  <name>dfs.hosts.exclude</name>

  <value>excludes</value>

</property>

 

<property>

 

<name>dfs.name.dir</name>          

 

<value>/hadoop/name</value>

 

  <description>Determines where on the local filesystem the DFS name node should store the name table. If this is a comma-delimited list of directories then the name table is replicated in all of the directories, for redundancy. </description>

 

</property>

 

</configuration>

 

l  把hadoop目錄下的conf/ hdfs-site.xml文件修改成如下:

<?xml version="1.0"?>

<?xml-stylesheet type="text/xsl" href="configuration.xsl"?>

 

<!-- Put site-specific property overrides in this file. -->

 

<configuration>

<property>

 

  <name>dfs.data.dir</name>          

 

  <value>/hadoop/data</value>

 

  <description>Determines where on the local filesystem an DFS data node should store its blocks. If this is a comma-delimited list of directories, then data will be stored in all named directories, typically on different devices. Directories that do not exist are ignored.</description>

 

</property>

 

<property>

 

  <name>dfs.replication</name>   

 

  <value>3</value>

 

  <description>Default block replication. The actual number of replications can be specified when the file is created. The default is used if replication is not specified in create time.</description>

 

</property>

</configuration>

 

l  把hadoop目錄下的conf/ mapred-site.xml文件修改成如下:

<?xml version="1.0"?>

<?xml-stylesheet type="text/xsl" href="configuration.xsl"?>

 

<!-- Put site-specific property overrides in this file. -->

 

<configuration>

<property>

 

<name>mapred.job.tracker</name>

 

  <value>ubuntu:9001</value>  

 

  <description>The host and port that the MapReduce job tracker runs at. If "local", then jobs are run in-process as a single map and reduce task.</description>

 

</property>

</configuration>

 

注意:

別忘了hadoop.tmp.dir,dfs.name.dir,dfs.data.dir參數,hadoop存放數據文件,名字空間等的目錄,格式化分佈式文件系統時會格式化這個目錄。

這裏指向了/hadoop,所以也要創建這個目錄,並且用戶歸屬也是hadoop:hadoop。

 

l  把hadoop目錄下的conf/ masters文件修改成如下:

ubuntu

 

l  把hadoop目錄下的conf/ slaves文件修改成如下:

ubuntu

ubuntu1

ubuntu2

 

 


3.5 分發hadoop安裝文件

我使用VMWare的克隆功能,將主機ubuntu完全克隆兩份:ubuntu1和ubuntu2,並修改相應的主機名和IP地址,這樣就可以簡單地保持hadoop環境基本配置相同。

 

如果是安裝在實體物理機上,把在ubuntu安裝的jdk,系統配置文件/etc/host,/etc/profile,hadoop安裝目錄拷貝到ubuntu1和ubuntu2相應的目錄。

 


3.6 SSH配置無密碼驗證配置

切換到Hadoop用戶,在Hadoop家目錄下面創建.ssh目錄:

$ cd

$ mkdir .ssh

 

在master節點(即主機ubuntu)上生成密鑰對:

$ ssh-keygen –t rsa

 

然後一直按[Enter]鍵,按默認的選項生成密鑰對保存在.ssh/id_rsa文件中。

然後執行命令:

$ ssh ~/.ssh

$ cp id_rsa.pub authorized_keys

$ scp authorized_keys ubuntu1:/home/hadoop/.ssh

$ scp authorized_keys ubuntu2:/home/hadoop/.ssh

 

從ubuntu向ubuntu1和ubuntu2發起SSH連接,第一次登錄時需要輸入密碼,以後就不需要了。

$ ssh ubuntu1

$ ssh ubuntu2

 

我們只需要配置從master向slaves發起SSH連接不需要密碼就可以了,但這樣只能在master(即在主機ubuntu)啓動或關閉hadoop服務。

 


3.7 運行hadoop

使用Hadoop用戶。

首先說明,hadoop命令和參數都是大小寫敏感的,該用大寫時用大寫,用小寫時用小寫,否則會執行錯誤。

 

         格式化分佈式文件系統:

$ hadoop namenode -format

 

在ubuntu上啓動hadoop守護進行:

$ start-all.sh

 

停止hadoop守護進程是:

$ stop-all.sh

 

         在ubuntu上查看運行的進程:

$ jps

2971 SecondaryNameNode

3043 JobTracker

2857 DataNode

4229 Jps

3154 TaskTracker

2737 NameNode

 

在ubuntu1上查看運行的進程:

$ jps

1005 DataNode

2275 Jps

1090 TaskTracker

 

         其它命令請參考相關資料。

 

在windows上通過WEB查看hadoop相關信息。

修改C:\WINDOWS\system32\drivers\etc\hosts文件,加入主機名與IP對應關係:

192.168.69.231   ubuntu

192.168.69.232   ubuntu1

192.168.69.233   ubuntu2

 

訪問:http://ubuntu:50030 可以查看JobTracker的運行狀態:

 

訪問:http://ubuntu:50070 可以查看NameNode及整個分佈式文件系統的狀態等:

 


3.8 運行WordCount實例

         WordCount是hadoop自帶的實例,統計一批文本文件中各單詞出現的資料,輸出到指定的output目錄中,輸出目錄如果已經存在會報錯。

$ cd /opt/hadoop

$ hadoop fs -mkdir input

$ hadoop fs -copyFromLocal /opt/hadoop/*.txt input/

$ hadoop jar hadoop-0.20.2-examples.jar wordcount input output

$ hadoop fs -cat output/*    #最後查看結果

 


 


4.    Windows下eclipse開發環境配置
4.1 系統環境配置

在windows上通過WEB查看hadoop相關信息。

修改C:\WINDOWS\system32\drivers\etc\hosts文件,加入主機名與IP對應關係:

192.168.69.231   ubuntu

192.168.69.232   ubuntu1

192.168.69.233   ubuntu2

 


4.2 安裝開發hadoop插件

         將hadoop安裝包hadoop\contrib\eclipse-plugin\hadoop-0.20.2-eclipse-plugin.jar拷貝到eclipse的插件目錄plugins下。

  需要注意的是插件版本(及後面開發導入的所有jar包)與運行的hadoop一致,否則可能會出現EOFException異常。

 

重啓eclipse,打開windows->open perspective->other->map/reduce 可以看到map/reduce開發視圖。

 


4.3 設置連接參數

    打開windows->show view->other-> map/reduce Locations視圖,在點擊大象後彈出的對話框(General tab)進行參數的添加:

 

         參數說明如下:

         Location name:任意

         map/reduce master:與mapred-site.xml裏面mapred.job.tracker設置一致。

DFS master:與core-site.xml裏fs.default.name設置一致。

User name: 服務器上運行hadoop服務的用戶名。

 

       然後是打開“Advanced parameters”設置面板,修改相應參數。上面的參數填寫以後,也會反映到這裏相應的參數:

主要關注下面幾個參數:

fs.defualt.name:與core-site.xml裏fs.default.name設置一致。

mapred.job.tracker:與mapred-site.xml裏面mapred.job.tracker設置一致。

dfs.replication:與hdfs-site.xml裏面的dfs.replication一致。

hadoop.tmp.dir:與core-site.xml裏hadoop.tmp.dir設置一致。

hadoop.job.ugi:並不是設置用戶名與密碼。是用戶與組名,所以這裏填寫hadoop,hadoop。

說明:第一次設置的時候可能是沒有hadoop.job.ugi和dfs.replication參數的,不要緊,確認保存。打開Project Explorer中DFS Locations目錄,應該可以年看到文件系統中的結構了。但是在/hadoop/mapred/system下卻沒有查看權限,如下圖:

 

而且刪除文件的時候也會報錯:

這個原因是我使用地本用戶Administrator(我是用管理員用戶登陸來地windows系統的)進行遠程hadoop系統操作,沒有權限。

 

此時再打開“Advanced parameters”設置面板,應該可以看到hadoop.job.ugi了,這個參數默認是本地操作系統的用戶名,如果不幸與遠程hadoop用戶不一致,那就要改過來了,將hadoop加在第一個,並用逗號分隔。如:

   保存配置後,重新啓動eclipse。/hadoop/mapred/system下就一目瞭然了,刪除文件也OK。


4.4 運行hadoop程序

首先將hadoop安裝包下面的所有jar包都導到eclipse工程裏。

然後建立一個類:DFSOperator.java,該類寫了四個基本方法:創建文件,刪除文件,把文件內容讀爲字符串,將字符串寫入文件。同時有個main函數,可以修改測試:

 

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;

import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.FSDataOutputStream;
import org.apache.hadoop.fs.FileSystem;
import org.apache.hadoop.fs.Path;

/**
 *
 * The utilities to operate file on hadoop hdfs.
 *
 * @author luolihui 2011-07-18
 *
 */
public class DFSOperator {
 
 private static final String ROOT_PATH = "hdfs:///";
 private static final int BUFFER_SIZE = 4096;
 
 /**
  * construct.
  */
 public DFSOperator(){}

     /**
     * Create a file on hdfs.The root path is /.<br>
     * for example: DFSOperator.createFile("/lory/test1.txt", true);
  * @param path  the file name to open
  * @param overwrite if a file with this name already exists, then if true, the file will be
  * @return true if delete is successful else IOException.
  * @throws IOException
  */
 public static boolean createFile(String path, boolean overwrite) throws IOException
 {
  //String uri = "hdfs://192.168.1.100:9000";
  //FileSystem fs1 = FileSystem.get(URI.create(uri), conf); 

  Configuration conf = new Configuration();
  FileSystem fs = FileSystem.get(conf);
  Path f = new Path(ROOT_PATH + path); 
  fs.create(f, overwrite);
  fs.close();
  return true;
 }
 
    /**
     * Delete a file on hdfs.The root path is /. <br>
     * for example: DFSOperator.deleteFile("/user/hadoop/output", true);
     * @param path the path to delete
     * @param recursive  if path is a directory and set to true, the directory is deleted else throws an exception. In case of a file the recursive can be set to either true or false.
     * @return true if delete is successful else IOException.
     * @throws IOException
     */
 public static boolean deleteFile(String path, boolean recursive) throws IOException
 {
  //String uri = "hdfs://192.168.1.100:9000";
  //FileSystem fs1 = FileSystem.get(URI.create(uri), conf); 
  
  Configuration conf = new Configuration();
  FileSystem fs = FileSystem.get(conf);
  Path f = new Path(ROOT_PATH + path); 
  fs.delete(f, recursive);
  fs.close();
  return true;
 }
 
 /**
  * Read a file to string on hadoop hdfs. From stream to string. <br>
  * for example: System.out.println(DFSOperator.readDFSFileToString("/user/hadoop/input/test3.txt"));
  * @param path the path to read
  * @return true if read is successful else IOException.
  * @throws IOException
  */
 public static String readDFSFileToString(String path) throws IOException
 {
  Configuration conf = new Configuration();
  FileSystem fs = FileSystem.get(conf);
  Path f = new Path(ROOT_PATH + path);
  InputStream in = null;
  String str = null;
  StringBuilder sb = new StringBuilder(BUFFER_SIZE);
  if (fs.exists(f))
  {
   in = fs.open(f);
   BufferedReader bf = new BufferedReader(new InputStreamReader(in));
   
   while ((str = bf.readLine()) != null)
   {
    sb.append(str);
    sb.append("\n");
   }
   
   in.close();
   bf.close();
   fs.close();
   return sb.toString();
  }
  else
  {
   return null;
  }
  
 }
 /**
  * Write string to a hadoop hdfs file. <br>
  * for example: DFSOperator.writeStringToDFSFile("/lory/test1.txt", "You are a bad man.\nReally!\n");
  * @param path the file where the string to write in.
  * @param string the context to write in a file.
  * @return true if write is successful else IOException.
  * @throws IOException
  */
 public static boolean writeStringToDFSFile(String path, String string) throws IOException
 {
  Configuration conf = new Configuration();
  FileSystem fs = FileSystem.get(conf);
  FSDataOutputStream os = null;
  Path f = new Path(ROOT_PATH + path);
  os = fs.create(f,true);
  os.writeBytes(string);
  
  os.close();
  fs.close();
  return true;
 }

 public static void main(String[] args)
 {
  try {
   DFSOperator.createFile("/lory/test1.txt", true);
   DFSOperator.deleteFile("/dfs_operator.txt", true);
   DFSOperator.writeStringToDFSFile("/lory/test1.txt", "You are a bad man.\nReally?\n");
   System.out.println(DFSOperator.readDFSFileToString("/lory/test1.txt"));
  } catch (IOException e) {
   // TODO Auto-generated catch block
   e.printStackTrace();
  }
  System.out.println("===end===");
 }
}
 

 

然後Run AsàRun on HadoopàChoose an exitsing server from the list belowàfinish.

 

結果很簡單(那個警告不管):

11/07/16 18:44:32 WARN conf.Configuration: DEPRECATED: hadoop-site.xml found in the classpath. Usage of hadoop-site.xml is deprecated. Instead use core-site.xml, mapred-site.xml and hdfs-site.xml to override properties of core-default.xml, mapred-default.xml and hdfs-default.xml respectively

You are a bad man.

Really?

 

===end===

 

也可以運行hadoop自帶的WorkCount程序,找到其源代碼導進來,然後設置輸入輸出參數,然後同樣“Run on hadoop”。具體步驟不再示範。

每“Run on hadoop”都會在workspace\.metadata\.plugins\org.apache.hadoop.eclipse下生成臨時jar包。不過第一次需要Run on hadoop,以後只需要點擊那運行的綠色按鈕了。


 


5.    錯誤及處理
5.1 安全模式問題

我在eclipse上刪除DFS上的文件夾時,出現下面錯誤:

錯誤提示說得也比較明示,是NameNode在安全模式中,其解決方案也一併給出。

類似的運行hadoop程序時,有時候會報以下錯誤:

org.apache.hadoop.dfs.SafeModeException: Cannot delete /user/hadoop/input. Name node is in safe mode

 

解除安全模式:

bin/hadoop dfsadmin -safemode leave 

 

用戶可以通過dfsadmin -safemode value  來操作安全模式,參數value的說明如下:

enter - 進入安全模式

leave - 強制NameNode離開安全模式

get -  返回安全模式是否開啓的信息

wait - 等待,一直到安全模式結束。

 


5.2 開發時報錯Permission denied

org.apache.hadoop.security.AccessControlException: org.apache.hadoop.security.AccessControlException: Permission denied: user=Administrator, access=WRITE, inode="test1.txt":hadoop:supergroup:rw-r--r--

    at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)

    at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:39)

    at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:27)

    at java.lang.reflect.Constructor.newInstance(Constructor.java:513)

    at org.apache.hadoop.ipc.RemoteException.instantiateException(RemoteException.java:96)

    at org.apache.hadoop.ipc.RemoteException.unwrapRemoteException(RemoteException.java:58)

    at org.apache.hadoop.hdfs.DFSClient$DFSOutputStream.<init>(DFSClient.java:2710)

    at org.apache.hadoop.hdfs.DFSClient.create(DFSClient.java:492)

    at org.apache.hadoop.hdfs.DistributedFileSystem.create(DistributedFileSystem.java:195)

    at org.apache.hadoop.fs.FileSystem.create(FileSystem.java:484)

    at org.apache.hadoop.fs.FileSystem.create(FileSystem.java:465)

    at org.apache.hadoop.fs.FileSystem.create(FileSystem.java:372)

    at com.kingdee.hadoop.DFSOperator.createFile(DFSOperator.java:46)

    at com.kingdee.hadoop.DFSOperator.main(DFSOperator.java:134)

 

解決方法是,在“Advanced parameters”設置面板,設置hadoop.job.ugi參數,將hadoop用戶加上去。

變爲:

 

然後重新在運行中”Run on hadoop”。

另一方法是改變要操作的文件的權限。

Permission denied: user=Administrator, access=WRITE, inode="test1.txt":hadoop:supergroup:rw-r--r--

  上面的意思是:test1.txt文件的訪問權限是rw-r--r--,歸屬組是supergroup,歸屬用戶是hadoop,現在使用Administrator用戶對test1.txt文件進行WRITE方式訪問,被拒絕了。

所以可以改變下test1.txt文件的訪問權限:

$ hadoop fs –chmod 777 /lory/test1.txt

$ hadoop fs –chmod 777 /lory     #或者上一級文件夾

  當然使用-chown命令也可以。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章