web-dev-qa-db-fra.com

Appeler un travail mapreduce à partir d'un simple programme Java

J'ai essayé d'appeler un travail mapreduce à partir d'un simple programme Java du même package. J'ai essayé de référencer le fichier jar mapreduce dans mon programme Java et de l'appeler à l'aide de la méthode runJar(String args[]) en passant également les chemins d'entrée et de sortie pour le mapreduce travail .. Mais le programme ne fonctionne pas .. 


Comment puis-je exécuter un tel programme où je viens d'utiliser passer entrée, sortie et chemin JAR à sa méthode principale? Est-il possible d'exécuter un travail mapreduce (jar) ?? Je veux le faire parce que je veux exécuter plusieurs travaux mapreduce les uns après les autres, où mon programme Java appelle chacun de ces travaux en faisant référence à son fichier jar. Si cela est possible, je pourrais aussi bien utiliser un simple servlet pour effectuer de tels appels. et se référer ses fichiers de sortie pour le but du graphique ..


/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

/**
 *
 * @author root
 */
import org.Apache.hadoop.util.RunJar;
import Java.util.*;

public class callOther {

    public static void main(String args[])throws Throwable
    {

        ArrayList arg=new ArrayList();

        String output="/root/Desktp/output";

        arg.add("/root/NetBeansProjects/wordTool/dist/wordTool.jar");

        arg.add("/root/Desktop/input");
        arg.add(output);

        RunJar.main((String[])arg.toArray(new String[0]));

    }
}
21
Ravi Trivedi

Oh, s'il vous plaît, ne le faites pas avec runJar, l'API Java est très bonne.

Voyez comment vous pouvez démarrer un travail à partir du code normal:

// create a configuration
Configuration conf = new Configuration();
// create a new job based on the configuration
Job job = new Job(conf);
// here you have to put your mapper class
job.setMapperClass(Mapper.class);
// here you have to put your reducer class
job.setReducerClass(Reducer.class);
// here you have to set the jar which is containing your 
// map/reduce class, so you can use the mapper class
job.setJarByClass(Mapper.class);
// key/value of your reducer output
job.setOutputKeyClass(Text.class);
job.setOutputValueClass(Text.class);
// this is setting the format of your input, can be TextInputFormat
job.setInputFormatClass(SequenceFileInputFormat.class);
// same with output
job.setOutputFormatClass(TextOutputFormat.class);
// here you can set the path of your input
SequenceFileInputFormat.addInputPath(job, new Path("files/toMap/"));
// this deletes possible output paths to prevent job failures
FileSystem fs = FileSystem.get(conf);
Path out = new Path("files/out/processed/");
fs.delete(out, true);
// finally set the empty out path
TextOutputFormat.setOutputPath(job, out);

// this waits until the job completes and prints debug out to STDOUT or whatever
// has been configured in your log4j properties.
job.waitForCompletion(true);

Si vous utilisez un cluster externe, vous devez mettre les informations suivantes dans votre configuration via:

// this should be like defined in your mapred-site.xml
conf.set("mapred.job.tracker", "jobtracker.com:50001"); 
// like defined in hdfs-site.xml
conf.set("fs.default.name", "hdfs://namenode.com:9000");

Cela ne devrait pas poser de problème lorsque le hadoop-core.jar est dans le chemin de classe des conteneurs d’applications . Mais je pense que vous devriez mettre une sorte d’indicateur de progression sur votre page Web, car la réalisation d’un travail hadoop peut prendre de quelques minutes à des heures;)

Pour YARN (> Hadoop 2)

Pour YARN, les configurations suivantes doivent être définies.

// this should be like defined in your yarn-site.xml
conf.set("yarn.resourcemanager.address", "yarn-manager.com:50001"); 

// framework is now "yarn", should be defined like this in mapred-site.xm
conf.set("mapreduce.framework.name", "yarn");

// like defined in hdfs-site.xml
conf.set("fs.default.name", "hdfs://namenode.com:9000");
31
Thomas Jungblut

Appel du travail MapReduce à partir d'une application Web Java (Servlet)

Vous pouvez appeler un travail MapReduce à partir d'une application Web à l'aide de l'API Java. Voici un petit exemple d'appel d'un travail MapReduce à partir d'un servlet. Les étapes sont indiquées ci-dessous:

Étape 1 : Commencez par créer une classe de servlet de pilote MapReduce. Développez également la carte et réduisez le service. Voici un exemple d'extrait de code:

CallJobFromServlet.Java

    public class CallJobFromServlet extends HttpServlet {

    protected void doPost(HttpServletRequest request,HttpServletResponse response) throws ServletException, IOException {

    Configuration conf = new Configuration();
    // Replace CallJobFromServlet.class name with your servlet class
        Job job = new Job(conf, " CallJobFromServlet.class"); 
        job.setJarByClass(CallJobFromServlet.class);
        job.setJobName("Job Name");
        job.setOutputKeyClass(Text.class);
        job.setOutputValueClass(Text.class);
        job.setMapperClass(Map.class); // Replace Map.class name with your Mapper class
        job.setNumReduceTasks(30);
        job.setReducerClass(Reducer.class); //Replace Reduce.class name with your Reducer class
        job.setMapOutputKeyClass(Text.class);
        job.setMapOutputValueClass(Text.class);
        job.setInputFormatClass(TextInputFormat.class);
        job.setOutputFormatClass(TextOutputFormat.class);

        // Job Input path
        FileInputFormat.addInputPath(job, new  
        Path("hdfs://localhost:54310/user/hduser/input/")); 
        // Job Output path
        FileOutputFormat.setOutputPath(job, new 
        Path("hdfs://localhost:54310/user/hduser/output")); 

        job.waitForCompletion(true);
   }
}

Étape 2 : Placez tous les fichiers jar associés (hadoop, jars spécifiques à l’application) dans le dossier lib du serveur Web (Tomcat, par exemple). C’est obligatoire pour accéder aux configurations Hadoop (le dossier hadoop ‘conf’ contient des fichiers de configuration xml, tels que core-site.xml, hdfs-site.xml, etc.). Copiez simplement les fichiers jar du dossier lib hadoop dans le répertoire lib du serveur Web (Tomcat) . La liste des noms de fichiers jar est la suivante:

1.  commons-beanutils-1.7.0.jar
2.  commons-beanutils-core-1.8.0.jar
3.  commons-cli-1.2.jar
4.  commons-collections-3.2.1.jar
5.  commons-configuration-1.6.jar
6.  commons-httpclient-3.0.1.jar
7.  commons-io-2.1.jar
8.  commons-lang-2.4.jar
9.  commons-logging-1.1.1.jar
10. hadoop-client-1.0.4.jar
11. hadoop-core-1.0.4.jar
12. jackson-core-asl-1.8.8.jar
13. jackson-mapper-asl-1.8.8.jar
14. jersey-core-1.8.jar

Étape 3 : Déployez votre application Web sur un serveur Web (dans le dossier "webapps" de Tomcat).

Étape 4 : Créez un fichier jsp et liez la classe servlet (CallJobFromServlet.Java) dans l'attribut d'action de formulaire. Voici un exemple d'extrait de code:

Index.jsp

<form id="trigger_hadoop" name="trigger_hadoop" action="./CallJobFromServlet ">
      <span class="back">Trigger Hadoop Job from Web Page </span> 
      <input type="submit" name="submit" value="Trigger Job" />      
</form>

Une autre façon de traiter les tâches déjà implémentées dans les exemples hadoop et nécessite également l'importation de jarres Hadoop .. appelez simplement la fonction principale statique de la classe de travail souhaitée avec la chaîne [] d'arguments appropriée

1
faridasabry

Parce que mapper et réduire les exécutions sur différentes machines, toutes vos classes et tous vos fichiers JAR référencés doivent être déplacés d'une machine à l'autre.

Si vous avez un package jar et que vous l'exécutez sur votre bureau, la réponse de ThomasJungblut est OK. Mais si vous exécutez Eclipse, cliquez avec le bouton droit sur votre classe et exécutez-le, cela ne fonctionne pas.

Au lieu de:

job.setJarByClass(Mapper.class);

Utilisation:

job.setJar("build/libs/hdfs-javac-1.0.jar");

En même temps, le manifeste de votre jarre doit inclure la propriété Main-Class, qui est votre classe principale.

Pour les utilisateurs de Gradle, vous pouvez mettre ces lignes dans build.gradle:

jar {
manifest {
    attributes("Main-Class": mainClassName)
}}
1
Jiang Libo

Vous pouvez faire de cette façon

public class Test {

    public static void main(String[] args) throws Exception {
        int res = ToolRunner.run(new Configuration(), new YourJob(), args);
        System.exit(res);

    }
0
techlearner

Je ne peux pas penser à beaucoup de façons de faire cela sans impliquer la bibliothèque hadoop-core (ou même comme l'a dit @ThomasJungblut, pourquoi vous voudriez).

Mais si vous en avez absolument besoin, vous pouvez configurer un serveur Oozie avec un flux de travail pour votre travail, puis utiliser l'interface de service Web Oozie pour soumettre le flux de travail à Hadoop.

Encore une fois, cela ressemble à beaucoup de travail pour quelque chose qui pourrait simplement être résolu en utilisant la réponse de Thomas (incluez le pot hadoop-core et utilisez son extrait de code)

0
Chris White