Opracowywanie programów MapReduce w języku Java dla usługi Apache Hadoop w usłudze HDInsight

Dowiedz się, jak za pomocą narzędzia Apache Maven utworzyć aplikację MapReduce opartą na języku Java, a następnie uruchomić ją za pomocą usługi Apache Hadoop w usłudze Azure HDInsight.

Wymagania wstępne

Konfigurowanie środowiska programowania

Środowisko używane w tym artykule było komputerem z systemem Windows 10. Polecenia zostały wykonane w wierszu polecenia, a różne pliki zostały edytowane za pomocą Notatnika. Odpowiednio zmodyfikuj środowisko.

W wierszu polecenia wprowadź poniższe polecenia, aby utworzyć środowisko robocze:

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

Tworzenie projektu Maven

  1. Wprowadź następujące polecenie, aby utworzyć projekt Maven o nazwie wordcountjava:

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

    To polecenie tworzy katalog o nazwie określonej przez artifactID parametr (wordcountjava w tym przykładzie). Ten katalog zawiera następujące elementy:

    • pom.xmlModel obiektów projektu (POM), który zawiera informacje i szczegóły konfiguracji używane do kompilowania projektu.
    • src\main\java\org\apache\hadoop\examples: Zawiera kod aplikacji.
    • src\test\java\org\apache\hadoop\examples: zawiera testy aplikacji.
  2. Usuń wygenerowany przykładowy kod. Usuń wygenerowane pliki AppTest.javatestów i aplikacji, a App.java następnie wprowadź poniższe polecenia:

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

Aktualizowanie modelu obiektów projektu

Aby uzyskać pełną dokumentację pliku pom.xml, zobacz https://maven.apache.org/pom.html. Otwórz pom.xml plik, wprowadzając poniższe polecenie:

notepad pom.xml

Dodawanie zależności

W pom.xmlpliku dodaj następujący tekst w <dependencies> sekcji :

<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>

Definiuje wymagane biblioteki (wymienione w obszarze <artifactId>) z określoną wersją (wymienioną w <wersji>). W czasie kompilacji te zależności są pobierane z domyślnego repozytorium Maven. Aby wyświetlić więcej, możesz użyć wyszukiwania repozytorium Maven .

Polecenie <scope>provided</scope> informuje narzędzie Maven, że te zależności nie powinny być spakowane z aplikacją, ponieważ są one dostarczane przez klaster usługi HDInsight w czasie wykonywania.

Ważne

Używana wersja powinna być zgodna z wersją usługi Hadoop w klastrze. Aby uzyskać więcej informacji na temat wersji, zobacz dokument dotyczący przechowywania wersji składników usługi HDInsight .

Konfiguracja kompilacji

Wtyczki Maven umożliwiają dostosowanie etapów kompilacji projektu. Ta sekcja służy do dodawania wtyczek, zasobów i innych opcji konfiguracji kompilacji.

Dodaj następujący kod do pom.xml pliku, a następnie zapisz i zamknij plik. Ten tekst musi znajdować się wewnątrz <project>...</project> tagów w pliku, na przykład między </dependencies> i </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>

Ta sekcja umożliwia skonfigurowanie wtyczki kompilatora Apache Maven i wtyczki Apache Maven Shade Plugin. Wtyczka kompilatora służy do kompilowania topologii. Wtyczka cieniowania służy do zapobiegania duplikowaniu licencji w pakiecie JAR utworzonym przez narzędzie Maven. Ta wtyczka służy do zapobiegania błędowi "zduplikowanych plików licencji" w czasie wykonywania w klastrze usługi HDInsight. Użycie wtyczki maven-shade-plugin z implementacją ApacheLicenseResourceTransformer uniemożliwia błąd.

Wtyczka maven-shade-plugin tworzy również plik jar uber, który zawiera wszystkie zależności wymagane przez aplikację.

Zapisz plik pom.xml.

Tworzenie aplikacji MapReduce

  1. Wprowadź poniższe polecenie, aby utworzyć i otworzyć nowy plik WordCount.java. Wybierz pozycję Tak po wyświetleniu monitu, aby utworzyć nowy plik.

    notepad src\main\java\org\apache\hadoop\examples\WordCount.java
    
  2. Następnie skopiuj i wklej poniższy kod Java do nowego pliku. Następnie zamknij plik.

    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);
        }
    }
    

    Zwróć uwagę, że nazwa pakietu to org.apache.hadoop.examples , a nazwa klasy to WordCount. Te nazwy są używane podczas przesyłania zadania MapReduce.

Kompilowanie i pakowanie aplikacji

wordcountjava W katalogu użyj następującego polecenia, aby skompilować plik JAR zawierający aplikację:

mvn clean package

To polecenie czyści wszystkie poprzednie artefakty kompilacji, pobiera wszystkie zależności, które nie zostały jeszcze zainstalowane, a następnie kompiluje i pakuje aplikację.

Po zakończeniu wordcountjava/target polecenia katalog zawiera plik o nazwie wordcountjava-1.0-SNAPSHOT.jar.

Uwaga

Plik wordcountjava-1.0-SNAPSHOT.jar jest uberjar, który zawiera nie tylko zadanie WordCount, ale także zależności, które zadanie wymaga w czasie wykonywania.

Przekazywanie pliku JAR i uruchamianie zadań (SSH)

Poniższe kroki umożliwiają scp skopiowanie pliku JAR do podstawowego węzła głównego bazy danych Apache HBase w klastrze usługi HDInsight. Polecenie ssh jest następnie używane do nawiązywania połączenia z klastrem i uruchamiania przykładu bezpośrednio w węźle głównym.

  1. Przekaż plik jar do klastra. Zastąp CLUSTERNAME ciąg nazwą klastra usługi HDInsight, a następnie wprowadź następujące polecenie:

    scp target/wordcountjava-1.0-SNAPSHOT.jar sshuser@CLUSTERNAME-ssh.azurehdinsight.net:
    
  2. Połącz się z klastrem. Zastąp CLUSTERNAME ciąg nazwą klastra usługi HDInsight, a następnie wprowadź następujące polecenie:

    ssh sshuser@CLUSTERNAME-ssh.azurehdinsight.net
    
  3. W sesji SSH użyj następującego polecenia, aby uruchomić aplikację MapReduce:

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

    To polecenie uruchamia aplikację MapReduce WordCount. Plik wejściowy to /example/data/gutenberg/davinci.txt, a katalog wyjściowy to /example/data/wordcountout. Zarówno plik wejściowy, jak i dane wyjściowe są przechowywane w domyślnym magazynie klastra.

  4. Po zakończeniu zadania użyj następującego polecenia, aby wyświetlić wyniki:

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

    Powinna zostać wyświetlona lista wyrazów i zliczeń z wartościami podobnymi do następującego tekstu:

    zeal    1
    zelus   1
    zenith  2
    

Następne kroki

W tym dokumencie przedstawiono sposób tworzenia zadania MapReduce w języku Java. Zapoznaj się z następującymi dokumentami, aby poznać inne sposoby pracy z usługą HDInsight.