2012-12-23 3 views
1

나는 매퍼/리듀서의 소스 코드를 받고, 매퍼/리듀서를 동적으로 컴파일하고, JAR 파일을 만드는 프로그램을 작성 중이다. 그런 다음이 JAR 파일을 hadoop 클러스터에서 실행해야한다.다른 자바 프로그램에서 Hadoop 작업 실행하기

마지막 부분에서는 필요한 모든 매개 변수를 내 코드를 통해 동적으로 설정했습니다. 그러나 지금 당면한 문제는 컴파일 할 때 컴파일 된 매퍼 및 감속기 클래스가 필요하다는 것입니다. 그러나 컴파일 할 때, 나는이 클래스들을 가지지 않고 런타임 동안 (예를 들어 원격 노드로부터 수신 된 메시지를 통해) 나중에 수신 될 것이다. 이 문제를 해결하는 방법에 대한 아이디어 나 제안은 감사하겠습니다.

다음은 job.setMapperClass (Mapper_Class.class) 및 class (Mapper_Class.class 및 Reducer_Class.class) 파일을 필요로하는 job.setReducerClass (Reducer_Class.class)에 문제가있는 마지막 부분의 코드입니다. 컴파일시에 존재하는 :

private boolean run_Hadoop_Job(String className){ 
try{ 
    System.out.println("Starting to run the code on Hadoop..."); 
    String[] argsTemp = { "project_test/input", "project_test/output" }; 
    // create a configuration 
    Configuration conf = new Configuration(); 
    conf.set("fs.default.name", "hdfs://localhost:54310"); 
    conf.set("mapred.job.tracker", "localhost:54311"); 
    conf.set("mapred.jar", jar_Output_Folder+ java.io.File.separator 
          + className+".jar"); 
    conf.set("mapreduce.map.class", "Mapper_Reducer_Classes$Mapper_Class.class"); 
    conf.set("mapreduce.reduce.class", "Mapper_Reducer_Classes$Reducer_Class.class"); 
    // create a new job based on the configuration 
    Job job = new Job(conf, "Hadoop Example for dynamically and programmatically compiling-running a job"); 
    job.setJarByClass(Platform.class); 
    //job.setMapperClass(Mapper_Class.class); 
    //job.setReducerClass(Reducer_Class.class); 

    // key/value of your reducer output 
    job.setOutputKeyClass(Text.class); 
    job.setOutputValueClass(IntWritable.class); 

    FileInputFormat.addInputPath(job, new Path(argsTemp[0])); 
    // this deletes possible output paths to prevent job failures 
    FileSystem fs = FileSystem.get(conf); 
    Path out = new Path(argsTemp[1]); 
    fs.delete(out, true); 
    // finally set the empty out path 
    FileOutputFormat.setOutputPath(job, new Path(argsTemp[1])); 

    //job.submit(); 
    System.exit(job.waitForCompletion(true) ? 0 : 1); 
    System.out.println("Job Finished!");   
} catch (Exception e) { return false; } 
return true; 
} 

는 개정 : 그래서 지금 ("mapreduce.map.class"내 mapper.class ")를 conf.set를 사용하여 매퍼 및 감속기를 지정하는 코드를 수정. 코드가 올바르게 컴파일되지만 실행될 때 다음 오류가 발생합니다.

ec 24, 2012 6:49:43 AM org.apache.hadoop.mapred.JobClien t monitorAndPrintJob 정보 : 작업 ID : attempt_201212240511_0006_m_000001_2, 상태 : 실패 java.lang.RuntimeException가 : java.lang.ClassNotFoundException가 : Configuration.java:809 org.apache.hadoop.conf.Configuration.getClass에서 Mapper_Reducer_Classes $ Mapper_Class.class () at org.apache.hadoop.mapreduce.JobContext.getMapperClass (JobContext.java:157) at org.apache.hadoop.mapred.MapTask.runNewMapper (MapTask.java:569) at org.apache.hadoop.mapred .MapTask.run (MapTask.java:305) at org.apache.hadoop.mapred.Child.main (Child.java:170)

답변

2

컴파일 할 때 가지고 있지 않다면 직접 설정하십시오. 다음과 같은 구성의 이름 :

conf.set("mapreduce.map.class", "org.what.ever.ClassName"); 
conf.set("mapreduce.reduce.class", "org.what.ever.ClassName"); 
+0

'tmpjars'라는 속성에'Hadoop' jar를 추가해야합니다. 그래서 다음과 같이 작동합니다 :'conf.set ("tmpjars", "/usr/local/hadoop/hadoop-core.jar,/usr/local/hadoop/hadoop-example.jar)'.Jar 경로는 분리되어야합니다. 쉼표로.이것은 상당히 해킹 된 것으로,이 병들이 실제로 클라이언트 시스템에 있다는 것을주의해야합니다 (Hadoop이이를 HDFS로 복사하고이를 작업 추적자에게 다운로드하기 위해). –

+0

토마스에게 감사드립니다. 이 부분을 알아 내고 코드가 올바르게 컴파일됩니다. 그러나 실행 중에 오류가 발생합니다. 이를 반영하기 위해 초기 게시물을 수정했습니다. 어떤 생각? – reza

+0

매퍼가'tmpjars'에 들어있는 병을 명시 적으로 추가 했습니까? –

0

동적으로 생성 될 클래스에 대한 클래스 개체에 대한 참조 만 필요합니다. foo.Mapper.class 대신 Class.for name("foo.Mapper")을 사용하십시오.

1

문제는 TaskTracker가 로컬 jRE의 클래스를 볼 수 없다는 것입니다.

나는 이런 식으로 알아 냈다. (Maven 프로젝트);

첫째, 자바 소스 코드, 모든 종속 항아리를 포함하여 응용 프로그램 jar 파일을 구축 할 것, pom.xml 파일을

<build> 
    <plugins> 
     <plugin> 
      <groupId>org.apache.maven.plugins</groupId> 
      <artifactId>maven-shade-plugin</artifactId> 
      <executions> 
       <execution> 
        <phase>package</phase> 
        <goals> 
         <goal>shade</goal> 
        </goals> 
       </execution> 
      </executions> 
      <configuration> 
       <filters> 
        <filter> 
         <artifact>*:*</artifact> 
         <excludes> 
          <exclude>META-INF/*.SF</exclude> 
          <exclude>META-INF/*.DSA</exclude> 
          <exclude>META-INF/*.RSA</exclude> 
         </excludes> 
        </filter> 
       </filters> 
       <finalName>sample</finalName> 
       <!-- 
       <finalName>uber-${artifactId}-${version}</finalName> 
       --> 
      </configuration> 
     </plugin> 
    </plugins> 
    </build> 

을이 플러그인을 추가 할 다음 행을 추가, 당신의 샘플이 포함됩니다. jom은 pom.xml의 target/sample.jar 태그 위에 작성되었습니다.

 Configuration config = new Configuration(); 
     config.set("fs.default.name", "hdfs://ip:port"); 
     config.set("mapred.job.tracker", "hdfs://ip:port"); 

     JobConf job = new JobConf(config); 
     job.setJar("target/sample.jar"); 

이러한 방식으로 작업 추적자는 작성한 클래스를 참조 할 수 있으며 ClassNotFoundException은 발생하지 않습니다.

+0

이것은 가장 좋은 답변입니다. hadoop 작업에 필요한 모든 것을 포함하고있는 그늘진 항아리를 사용하고 싶지는 않을 것입니다. 그리고 그 모든 것들을 외부 java 프로그램을위한 classpath에 보관하십시오. 항아리 충돌이나 기타 문제가있을 수 있습니다. 경로를 통해 음영 처리 된 jar를 참조하면 외부 프로그램에서 추상화되어 내장 API를 통해 hadoop 클러스터로 전송됩니다. 해당 프로그램에 필요한 특정 종속성 만 포함하는 외부 프로그램에서 사용하는 다른 jar를 빌드 할 수 있습니다. – Galuvian

관련 문제