Delen via


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

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

Vereiste voorwaarden

De ontwikkelomgeving configureren

De omgeving die voor dit artikel wordt gebruikt, was een computer met Windows 10. De opdrachten zijn uitgevoerd in een opdrachtregelvenster en de verschillende bestanden zijn bewerkt met Kladblok. Wijzig dienovereenkomstig 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 wordcountjavate 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 parameter artifactID (wordcountjava in dit voorbeeld.) Deze map bevat de volgende items:

    • pom.xml - De Project Object Model (POM) die 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 door de onderstaande opdrachten in te voeren:

    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 bestand pom.xml https://maven.apache.org/pom.html. Open pom.xml door de onderstaande opdracht in te voeren:

notepad pom.xml

Afhankelijkheden toevoegen

In pom.xml, voeg in de <dependencies> sectie de volgende tekst 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 Maven-repository zoeken gebruiken om meer te bekijken.

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

Belangrijk

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

Buildconfiguratie

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 en sla het bestand op en sluit het. Deze tekst moet zich in de <project>...</project> tags in het bestand, 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 shade plug-in wordt gebruikt om dubbele licenties te voorkomen in het JAR-pakket dat is gebouwd met Maven. Deze invoegtoepassing wordt gebruikt om de fout 'dubbele licentiebestanden' tijdens runtime op het HDInsight-cluster te voorkomen. 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 te maken en te openen WordCount.java. 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 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 dat de klassenaam WordCountis. 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, worden eventuele afhankelijkheden gedownload die nog niet zijn geïnstalleerd en worden 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.

De JAR uploaden en taken uitvoeren (SSH)

Met de volgende stappen scp kopieert u het JAR-bestand naar het primaire hoofdknooppunt van uw Apache HBase-cluster in HDInsight. 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 vervolgens 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 vervolgens 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 WordCount MapReduce-toepassing 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 moet een lijst met woorden en aantallen ontvangen, 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.