Java MapReduce-programma's ontwikkelen voor Apache Hadoop in HDInsight

Meer informatie over het gebruik van Apache Maven om een MapReduce-toepassing op basis van Java te maken en deze vervolgens uit te voeren met Apache Hadoop in Azure HDInsight.

Vereisten

De ontwikkelomgeving configureren

De omgeving die voor dit artikel werd gebruikt, was een computer met Windows 10. De opdrachten zijn uitgevoerd in een opdrachtprompt en de verschillende bestanden zijn bewerkt met Kladblok. Pas dienovereenkomstig aan voor uw omgeving.

Voer vanaf een opdrachtprompt de onderstaande opdrachten in om een werkomgeving te maken:

IF NOT EXIST C:\HDI MKDIR C:\HDI
cd C:\HDI

Een Maven-project maken

  1. Voer de volgende opdracht in om een Maven-project met de naam wordcountjava te maken:

    mvn archetype:generate -DgroupId=org.apache.hadoop.examples -DartifactId=wordcountjava -DarchetypeArtifactId=maven-archetype-quickstart -DinteractiveMode=false
    

    Met deze opdracht maakt u een map met de naam die is opgegeven door de artifactID parameter (wordcountjava in dit voorbeeld.) Deze map bevat de volgende items:

    • pom.xml - Het Project Object Model (POM) dat informatie en configuratiegegevens bevat die worden gebruikt om het project te bouwen.
    • src\main\java\org\apache\hadoop\examples: Bevat uw toepassingscode.
    • src\test\java\org\apache\hadoop\examples: bevat tests voor uw toepassing.
  2. Verwijder de gegenereerde voorbeeldcode. Verwijder de gegenereerde test- en toepassingsbestanden AppTest.javaen App.java voer de onderstaande opdrachten in:

    cd wordcountjava
    DEL src\main\java\org\apache\hadoop\examples\App.java
    DEL src\test\java\org\apache\hadoop\examples\AppTest.java
    

Het projectobjectmodel bijwerken

Zie voor een volledige verwijzing naar het pom.xml-bestand https://maven.apache.org/pom.html. Open pom.xml door de onderstaande opdracht in te voeren:

notepad pom.xml

Afhankelijkheden toevoegen

Voeg pom.xmlin de sectie de volgende tekst <dependencies> toe:

<dependency>
    <groupId>org.apache.hadoop</groupId>
    <artifactId>hadoop-mapreduce-examples</artifactId>
    <version>2.7.3</version>
    <scope>provided</scope>
</dependency>
<dependency>
    <groupId>org.apache.hadoop</groupId>
    <artifactId>hadoop-mapreduce-client-common</artifactId>
    <version>2.7.3</version>
    <scope>provided</scope>
</dependency>
<dependency>
    <groupId>org.apache.hadoop</groupId>
    <artifactId>hadoop-common</artifactId>
    <version>2.7.3</version>
    <scope>provided</scope>
</dependency>

Hiermee definieert u de vereiste bibliotheken (vermeld in <artifactId>) met een specifieke versie (vermeld in <versie>). Tijdens het compileren worden deze afhankelijkheden gedownload uit de standaard-Maven-opslagplaats. U kunt de zoekopdracht in de Maven-opslagplaats gebruiken om meer te bekijken.

De <scope>provided</scope> vertelt Maven dat deze afhankelijkheden niet met de toepassing moeten worden verpakt, omdat ze tijdens runtime worden geleverd door het HDInsight-cluster.

Belangrijk

De gebruikte versie moet overeenkomen met de versie van Hadoop die aanwezig is op uw cluster. Zie het document HDInsight-onderdeelversiebeheer voor meer informatie over versies.

Configuratie compileren

Met Maven-invoegtoepassingen kunt u de buildfasen van het project aanpassen. Deze sectie wordt gebruikt om invoegtoepassingen, resources en andere buildconfiguratieopties toe te voegen.

Voeg de volgende code toe aan het pom.xml bestand, sla het bestand op en sluit het. Deze tekst moet zich in de <project>...</project> tags in het bestand vinden, bijvoorbeeld tussen </dependencies> en </project>.

<build>
    <plugins>
    <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-shade-plugin</artifactId>
        <version>2.3</version>
        <configuration>
        <transformers>
            <transformer implementation="org.apache.maven.plugins.shade.resource.ApacheLicenseResourceTransformer">
            </transformer>
        </transformers>
        </configuration>
        <executions>
        <execution>
            <phase>package</phase>
                <goals>
                <goal>shade</goal>
                </goals>
        </execution>
        </executions>
        </plugin>
    <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-compiler-plugin</artifactId>
        <version>3.6.1</version>
        <configuration>
        <source>1.8</source>
        <target>1.8</target>
        </configuration>
    </plugin>
    </plugins>
</build>

In deze sectie worden de Apache Maven Compiler-invoegtoepassing en de Apache Maven Shade-invoegtoepassing geconfigureerd. De compiler-invoegtoepassing wordt gebruikt om de topologie te compileren. De schaduwinvoegtoepassing wordt gebruikt om duplicatie van licenties te voorkomen in het JAR-pakket dat is gebouwd door Maven. Deze invoegtoepassing wordt gebruikt om een fout 'dubbele licentiebestanden' te voorkomen tijdens runtime op het HDInsight-cluster. Het gebruik van maven-shade-plugin met de ApacheLicenseResourceTransformer implementatie voorkomt de fout.

De maven-shade-plugin produceert ook een uber jar die alle afhankelijkheden bevat die vereist zijn voor de toepassing.

Sla het bestand pom.xml op.

De MapReduce-toepassing maken

  1. Voer de onderstaande opdracht in om een nieuw bestand WordCount.javate maken en te openen. Selecteer Ja bij de prompt om een nieuw bestand te maken.

    notepad src\main\java\org\apache\hadoop\examples\WordCount.java
    
  2. Kopieer en plak vervolgens de onderstaande Java-code in het nieuwe bestand. Sluit vervolgens het bestand.

    package org.apache.hadoop.examples;
    
    import java.io.IOException;
    import java.util.StringTokenizer;
    import org.apache.hadoop.conf.Configuration;
    import org.apache.hadoop.fs.Path;
    import org.apache.hadoop.io.IntWritable;
    import org.apache.hadoop.io.Text;
    import org.apache.hadoop.mapreduce.Job;
    import org.apache.hadoop.mapreduce.Mapper;
    import org.apache.hadoop.mapreduce.Reducer;
    import org.apache.hadoop.mapreduce.lib.input.FileInputFormat;
    import org.apache.hadoop.mapreduce.lib.output.FileOutputFormat;
    import org.apache.hadoop.util.GenericOptionsParser;
    
    public class WordCount {
    
        public static class TokenizerMapper
            extends Mapper<Object, Text, Text, IntWritable>{
    
        private final static IntWritable one = new IntWritable(1);
        private Text word = new Text();
    
        public void map(Object key, Text value, Context context
                        ) throws IOException, InterruptedException {
            StringTokenizer itr = new StringTokenizer(value.toString());
            while (itr.hasMoreTokens()) {
            word.set(itr.nextToken());
            context.write(word, one);
            }
        }
    }
    
    public static class IntSumReducer
            extends Reducer<Text,IntWritable,Text,IntWritable> {
        private IntWritable result = new IntWritable();
    
        public void reduce(Text key, Iterable<IntWritable> values,
                            Context context
                            ) throws IOException, InterruptedException {
            int sum = 0;
            for (IntWritable val : values) {
            sum += val.get();
            }
            result.set(sum);
            context.write(key, result);
        }
    }
    
    public static void main(String[] args) throws Exception {
        Configuration conf = new Configuration();
        String[] otherArgs = new GenericOptionsParser(conf, args).getRemainingArgs();
        if (otherArgs.length != 2) {
            System.err.println("Usage: wordcount <in> <out>");
            System.exit(2);
        }
        Job job = new Job(conf, "word count");
        job.setJarByClass(WordCount.class);
        job.setMapperClass(TokenizerMapper.class);
        job.setCombinerClass(IntSumReducer.class);
        job.setReducerClass(IntSumReducer.class);
        job.setOutputKeyClass(Text.class);
        job.setOutputValueClass(IntWritable.class);
        FileInputFormat.addInputPath(job, new Path(otherArgs[0]));
        FileOutputFormat.setOutputPath(job, new Path(otherArgs[1]));
        System.exit(job.waitForCompletion(true) ? 0 : 1);
        }
    }
    

    U ziet dat de pakketnaam is org.apache.hadoop.examples en de klassenaam is WordCount. U gebruikt deze namen wanneer u de MapReduce-taak verzendt.

De toepassing bouwen en verpakken

Gebruik vanuit de wordcountjava map de volgende opdracht om een JAR-bestand te maken dat de toepassing bevat:

mvn clean package

Met deze opdracht worden eventuele eerdere buildartefacten opgeschoond, eventuele afhankelijkheden gedownload die nog niet zijn geïnstalleerd en wordt vervolgens de toepassing gebouwd en verpakt.

Zodra de opdracht is voltooid, bevat de wordcountjava/target map een bestand met de naam wordcountjava-1.0-SNAPSHOT.jar.

Notitie

Het wordcountjava-1.0-SNAPSHOT.jar bestand is een uberjar, die niet alleen de WordCount-taak bevat, maar ook afhankelijkheden die de taak tijdens runtime vereist.

Het JAR uploaden en taken uitvoeren (SSH)

De volgende stappen worden gebruikt scp om het JAR-bestand te kopiëren naar het primaire hoofdknooppunt van uw Apache HBase in HDInsight-cluster. De ssh opdracht wordt vervolgens gebruikt om verbinding te maken met het cluster en het voorbeeld rechtstreeks op het hoofdknooppunt uit te voeren.

  1. Upload het JAR-bestand naar het cluster. Vervang door CLUSTERNAME de naam van uw HDInsight-cluster en voer de volgende opdracht in:

    scp target/wordcountjava-1.0-SNAPSHOT.jar sshuser@CLUSTERNAME-ssh.azurehdinsight.net:
    
  2. Maak verbinding met het cluster. Vervang door CLUSTERNAME de naam van uw HDInsight-cluster en voer de volgende opdracht in:

    ssh sshuser@CLUSTERNAME-ssh.azurehdinsight.net
    
  3. Gebruik vanuit de SSH-sessie de volgende opdracht om de MapReduce-toepassing uit te voeren:

    yarn jar wordcountjava-1.0-SNAPSHOT.jar org.apache.hadoop.examples.WordCount /example/data/gutenberg/davinci.txt /example/data/wordcountout
    

    Met deze opdracht wordt de toepassing WordCount MapReduce gestart. Het invoerbestand is /example/data/gutenberg/davinci.txten de uitvoermap is /example/data/wordcountout. Zowel het invoerbestand als de uitvoer worden opgeslagen in de standaardopslag voor het cluster.

  4. Zodra de taak is voltooid, gebruikt u de volgende opdracht om de resultaten weer te geven:

    hdfs dfs -cat /example/data/wordcountout/*
    

    U ontvangt een lijst met woorden en aantallen, met waarden die vergelijkbaar zijn met de volgende tekst:

    zeal    1
    zelus   1
    zenith  2
    

Volgende stappen

In dit document hebt u geleerd hoe u een Java MapReduce-taak ontwikkelt. Zie de volgende documenten voor andere manieren om met HDInsight te werken.