Écrire et exécuter des tâches Spark Scala sur Cloud Dataproc

Ce tutoriel illustre différentes méthodes pour créer une tâche Spark Scala et l'envoyer à un cluster Cloud Dataproc. Vous allez ainsi découvrir comment :

  • écrire et compiler une application Spark Scala "Hello World" sur une machine locale à partir de la ligne de commande en utilisant le REPL Scala (Read-Evaluate-Print-Loop ou interpréteur interactif), l'outil de compilation SBT ou l'IDE Eclipse à l'aide du plug-in IDE Scala pour Eclipse ;
  • empaqueter des classes Scala compilées dans un fichier JAR avec un fichier manifeste ;
  • envoyer le fichier JAR Scala à une tâche Spark qui s'exécute sur votre cluster Cloud Dataproc ;
  • examiner les résultats de la tâche Scala dans Google Cloud Console.

Ce tutoriel vous explique également comment :

  • écrire et exécuter une tâche MapReduce Spark Scala "WordCount" directement sur un cluster Cloud Dataproc à l'aide du REPL spark-shell ;

  • exécuter des exemples Apache Spark et Hadoop pré-installés sur un cluster.

Configurer un projet Google Cloud Platform

Si ce n'est pas déjà fait, effectuez les opérations suivantes :

  1. Configurer un projet
  2. Créer un bucket Cloud Storage
  3. Créer un cluster Cloud Dataproc

Écrire et compiler le code Scala en local

Pour les besoins de ce tutoriel, nous allons effectuer un exercice simple, à savoir écrire une application Scala "Hello World" à l'aide du REPL Scala, de l'interface de ligne de commande SBT ou du plug-in IDE Scala pour Eclipse. Cette application sera créée en local sur votre machine de développement.

Utiliser Scala

  1. Téléchargez les fichiers binaires Scala depuis la page d'installation de Scala.
  2. Décompressez le fichier, définissez la variable d'environnement SCALA_HOME, puis ajoutez-la à votre chemin d'accès, comme indiqué dans les instructions d'installation de Scala. Exemple :

    export SCALA_HOME=/usr/local/share/scala
    export PATH=$PATH:$SCALA_HOME/
    

  3. Lancez le REPL Scala.

    $ scala
    Welcome to Scala version ...
    Type in expressions to have them evaluated.
    Type :help for more information.
    scala>
    

  4. Copiez et collez le code HelloWorld dans le REPL Scala.

    object HelloWorld {
      def main(args: Array[String]): Unit = {
        println("Hello, world!")
      }
    }
    
    

  5. Enregistrez HelloWorld.scala et quittez le REPL.

    scala> :save HelloWorld.scala
    scala> :q
    

  6. Effectuez la compilation avec scalac.

    $ scalac HelloWorld.scala
    

  7. Répertoriez les fichiers .class compilés.

    $ ls HelloWorld*.class
    HelloWorld$.class   HelloWorld.class
    

Utiliser SBT

  1. Téléchargez SBT.

  2. Créez un projet "HelloWorld", comme illustré ci-dessous.

    $ mkdir hello
    $ cd hello
    $ echo \
    'object HelloWorld {def main(args: Array[String]) = println("Hello, world!")}' > \
    HelloWorld.scala
    

  3. Créez un fichier de configuration sbt.build pour définir le paramètre artifactName (nom du fichier JAR que vous allez générer ci-dessous) sur "HelloWorld.jar" (consultez la section sur la modification des artefacts par défaut).

    echo \
    'artifactName := { (sv: ScalaVersion, module: ModuleID, artifact: Artifact) =>
    "HelloWorld.jar" }' > \
    build.sbt
    

  4. Lancez SBT et exécutez le code.

    $ sbt
    [info] Set current project to hello ...
    > run
    ... Compiling 1 Scala source to .../hello/target/scala-.../classes...
    ... Running HelloWorld
    Hello, world!
    [success] Total time: 3 s ...
    

  5. Empaquetez le code dans un fichier JAR avec un fichier manifeste indiquant le point d'entrée de la classe principale (HelloWorld), puis quittez l'outil.

    > package
    ... Packaging .../hello/target/scala-.../HelloWorld.jar ...
    ... Done packaging.
    [success] Total time: ...
    > exit
    

Utiliser le plug-in SBT pour Eclipse

  1. Installez le plug-in SBT pour Eclipse.

  2. Sélectionnez/Créez un espace de travail et démarrez un nouveau projet Scala.

  3. Sur la page Create a Scala project (Créer un projet Scala), nommez le projet "HelloWorld", puis cliquez sur "Finish" (Terminer) pour accepter les paramètres par défaut.

  4. Sélectionnez le dossier src dans le volet de gauche "Package Explorer" (Explorateur de packages), puis sélectionnez New → Scala Object (Nouveau → Objet Scala).

  5. Insérez "HelloWorld" comme nom d'objet Scala dans la boîte de dialogue Create New File (Créer un fichier), puis cliquez sur "Finish" (Terminer).

  6. Le fichier HelloWorld.scala est créé avec un modèle d'objet HelloWorld. Complétez le modèle pour terminer la définition de l'objet HelloWorld, comme suit :

    object HelloWorld {
      def main(args: Array[String]): Unit = {
        println("Hello, world!")
      }
    }
    
    

  7. Cliquez sur le document HelloWorld.scala ou sélectionnez son nom dans le volet de gauche "Package Explorer" (Explorateur de packages). Ensuite, effectuez un clic droit et sélectionnez Run As → Scala Application (Exécuter en tant que → Application Scala) pour compiler et exécuter l'application.

  8. La console indique que l'application a été compilée et exécutée correctement.

  9. Les fichiers de classe compilés se trouvent dans le dossier bin de votre projet, dans l'espace de travail Eclipse. Utilisez-les pour créer un fichier JAR (consultez la section Créer un fichier JAR).

Créer un fichier JAR

Créez un fichier JAR avec SBT ou à l'aide de la commande jar.

Utiliser SBT

La commande SBT package crée un fichier JAR (consultez la section Utiliser SBT).

Créer manuellement un fichier JAR

  1. Basculez vers le répertoire (commande cd) où sont stockés vos fichiers HelloWorld*.class compilés, puis exécutez la commande suivante pour empaqueter les fichiers de classe dans un fichier JAR avec un fichier manifeste qui spécifie le point d'entrée de la classe principale (HelloWorld).
    $ jar cvfe HelloWorld.jar HelloWorld HelloWorld*.class
    added manifest
    adding: HelloWorld$.class(in = 637) (out= 403)(deflated 36%)
    adding: HelloWorld.class(in = 586) (out= 482)(deflated 17%)
    

Copier le fichier JAR dans Cloud Storage

  1. Exécutez la commande gsutil pour copier le fichier JAR dans un bucket Cloud Storage de votre projet.
$ gsutil cp HelloWorld.jar gs://<bucket-name>/
Copying file://HelloWorld.jar [Content-Type=application/java-archive]...
Uploading   gs://bucket-name/HelloWorld.jar:         1.46 KiB/1.46 KiB

Envoyer un fichier JAR à une tâche Spark Cloud Dataproc

  1. Utilisez Cloud Console pour envoyer le fichier JAR à votre tâche SPARK Cloud Dataproc.

    • Renseignez les champs de la page Submit a job (Envoyer une tâche) comme suit :
      • Cluster : sélectionnez le nom de votre cluster dans la liste.
      • Job type (Type de tâche) : Spark.
      • Main class or jar (Classe principale ou fichier JAR) : indiquez le chemin d'URI Cloud Storage à votre fichier JAR HelloWorld (gs://your-bucket-name/HelloWorld.jar). Si votre fichier JAR n'inclut pas de fichier manifeste qui spécifie le point d'entrée de votre code ("Main-Class: HelloWorld"), le champ "Main class or jar" (Classe principale ou fichier JAR) doit indiquer le nom de votre classe principale ("HelloWorld"). Vous devez en outre indiquer le chemin d'URI à votre fichier JAR (gs://your-bucket-name/HelloWorld.jar) dans le champ "Jar files" (Fichiers JAR).
  2. Cliquez sur Envoyer pour démarrer la tâche. Une fois la tâche démarrée, elle est ajoutée à la liste "Jobs" (Tâches).

  3. Cliquez sur l'ID de la tâche pour ouvrir la page Jobs (Tâches) qui affiche les résultats du pilote de la tâche.

Écrire et exécuter du code Spark Scala à l'aide du REPL spark-shell du cluster

Vous pouvez développer des applications Scala directement sur votre cluster Cloud Dataproc. Hadoop et Spark sont pré-installés sur les clusters Cloud Dataproc et configurés avec le connecteur Cloud Storage. De cette façon, votre code peut lire directement des données depuis Cloud Storage et en écrire sur ce service.

Cet exemple vous montre comment vous connecter en SSH au nœud maître du cluster Cloud Dataproc de votre projet, puis utiliser le REPL spark-shell pour créer et exécuter une application MapReduce Scala "WordCount".

  1. Connectez-vous en SSH au nœud maître du cluster Cloud Dataproc.
    1. Accédez à la page Clusters Cloud Dataproc de votre projet dans Cloud Console, puis cliquez sur le nom de votre cluster.
    2. Sur la page de détails du cluster, sélectionnez l'onglet "VM Instances" (Instances de VM), puis cliquez sur la sélection SSH qui s'affiche à droite du nom du nœud maître de votre cluster.
      Une fenêtre de navigateur s'ouvre dans votre répertoire d'accueil sur le nœud maître.
      Connected, host fingerprint: ssh-rsa 2048 ...
      ...
      user@clusterName-m:~$
      
  2. Lancez spark-shell.
    $ spark-shell
    ...
    Using Scala version ...
    Type in expressions to have them evaluated.
    Type :help for more information.
    ...
    Spark context available as sc.
    ...
    SQL context available as sqlContext.
    scala>
    
  3. Créez un ensemble de données distribué résilient (RDD, Resilient Distributed Dataset) à partir d'un extrait d'une œuvre de Shakespeare situé dans un bucket Cloud Storage public.
    scala> val text_file = sc.textFile("gs://pub/shakespeare/rose.txt")
    
  4. Exécutez une commande MapReduce "WordCount" sur le texte, puis affichez le résultat wordcounts.
    scala> val wordCounts = text_file.flatMap(line => line.split(" ")).map(word =>
    (word, 1)).reduceByKey((a, b) => a + b)
    scala> wordCounts.collect
    ... Array((call,1), (What's,1), (sweet.,1), (we,1), (as,1), (name?,1), (any,1), (other,1),
    (rose,1), (smell,1), (name,1), (a,2), (would,1), (in,1), (which,1), (That,1), (By,1))
    
  5. Enregistrez les valeurs de <bucket-name>/wordcounts-out dans Cloud Storage, puis quittez scala-shell.
    scala> wordCounts.saveAsTextFile("gs://<bucket-name>/wordcounts-out/")
    scala> exit
    
  6. Utilisez gsutil pour répertorier les fichiers de sortie et afficher leur contenu.
    $ gsutil ls gs://bucket-name/wordcounts-out/
    gs://spark-scala-demo-bucket/wordcounts-out/
    gs://spark-scala-demo-bucket/wordcounts-out/_SUCCESS
    gs://spark-scala-demo-bucket/wordcounts-out/part-00000
    gs://spark-scala-demo-bucket/wordcounts-out/part-00001
    
  7. Vérifiez le contenu de gs://<bucket-name>/wordcounts-out/part-00000.
    $ gsutil cat gs://bucket-name/wordcounts-out/part-00000
    (call,1)
    (What's,1)
    (sweet.,1)
    (we,1)
    (as,1)
    (name?,1)
    (any,1)
    (other,1)
    

Exécuter un exemple de code pré-installé

Le nœud maître Cloud Dataproc contient des fichiers JAR exécutables avec des exemples Apache Hadoop et Spark standards.

Type de fichier JAR Master node /usr/lib/ location Source GitHub Documents Apache
Hadoop hadoop-mapreduce/hadoop-mapreduce-examples.jar lien source Tutoriel MapReduce
Spark spark/lib/spark-examples.jar lien source Exemples Spark

Envoyer des exemples à votre cluster à partir de la ligne de commande

Vous pouvez envoyer des exemples à partir de votre machine de développement locale à l'aide de l'outil de ligne de commande gcloud du SDK Cloud (consultez la section Utiliser Google Cloud Console pour envoyer des tâches à partir de Cloud Console).

Exemple d'application "WordCount" Hadoop

gcloud dataproc jobs submit hadoop --cluster=cluster-name \
    --region=region \
    --jars=file:///usr/lib/hadoop-mapreduce/hadoop-mapreduce-examples.jar \
    --class=org.apache.hadoop.examples.WordCount \
    -- URI of input file URI of output file

Exemple d'application "WordCount" Spark

gcloud dataproc jobs submit spark --cluster=cluster-name \
    --region=region \
    --jars=file:///usr/lib/spark/examples/jars/spark-examples.jar \
    --class=org.apache.spark.examples.JavaWordCount \
    -- URI of input file

Arrêter votre cluster

Pour éviter les frais récurrents, arrêtez votre cluster et supprimez les ressources Cloud Storage (bucket et fichiers Cloud Storage) utilisées pour ce tutoriel.

Pour arrêter un cluster :

gcloud dataproc clusters delete cluster-name \
    --region=region

Pour supprimer le fichier JAR de Cloud Storage :

gsutil rm gs://bucket-name/HelloWorld.jar

Vous pouvez supprimer un bucket, ainsi que l'ensemble des dossiers et fichiers qu'il contient, à l'aide de la commande suivante :

gsutil rm -r gs://bucket-name/

Étape suivante