Utilisation du connecteur HDFS avec Spark

Introduction

Cet article fournit une présentation qui illustre l'utilisation du connecteur HDFS avec le cadre d'application Spark. Pour la présentation, nous utilisons le système d'exploitation Oracle Linux 7.4 et nous exécutons Spark en tant que système autonome sur un seul ordinateur.

Préalables

Voici les préalables pour la présentation :

  • Vous devez avoir l'autorisation de créer une instance de calcul. Pour obtenir des instructions, voir Création d'une instance.
  • Vous devez être en mesure de vous connecter à l'instance de service que vous avez lancée. Pour plus d'informations, voir Connexion à une instance.
  • Vous devez disposer de l'OCID, de l'empreinte numérique et de la clé privée appropriés pour l'utilisateur Identity and Access Management (IAM) que vous utiliserez pour interagir avec un service de stockage d'objets. Pour plus d'informations, voir Configuration et préalables.
  • Vous devez avoir un seau de stockage d'objets auquel vous pouvez vous connecter.
  • L'utilisateur IAM doit pouvoir lire et écrire dans ce seau à l'aide de la console.

Utilisation de Spark

Installer Spark et ses dépendances

Note

Pour les besoins de cet exemple, installez Spark dans le répertoire de base de l'utilisateur courant. Notez que pour les scénarios de production, vous ne le feriez pas.
Note

Les versions 2.7.7.0 et ultérieures n'installent plus toutes les dépendances de tierce partie requises. Les dépendances de tierce partie requises sont regroupées sous le dossier third-party/lib de l'archive zip et doivent être installées manuellement.
  1. Créez une instance de calcul de votre service. Pour obtenir des instructions, voir Création d'une instance.
  2. Assurez-vous que votre instance de service dispose d'une adresse IP publique pour que vous puissiez vous connecter à l'aide d'une connexion SSH. Pour plus d'informations, voir Connexion à une instance.
  3. Connectez-vous à votre instance de service à l'aide d'une connexion SSH.
  4. Installez Spark et ses dépendances, Java et Scala en utilisant les exemples de code suivants.
# We'll use wget to download some of the artifacts that need to be installed
sudo yum install wget
 
# First install Java
sudo yum install java-1.8.0-openjdk.x86_64
export JAVA_HOME=/usr/lib/jvm/jre-1.8.0-openjdk
# Should be something like: OpenJDK Runtime Environment (build 1.8.0_161-b14)
java -version
 
# Then install Scala
wget https://downloads.lightbend.com/scala/2.12.4/scala-2.12.4.rpm
sudo yum install scala-2.12.4.rpm
# Should be something like: Scala code runner version 2.12.4 -- Copyright 2002-2017, LAMP/EPFL and Lightbend, Inc.
scala -version
 
# Then download Spark
wget https://archive.apache.org/dist/spark/spark-2.2.1/spark-2.2.1-bin-hadoop2.7.tgz
tar xvf spark-2.2.1-bin-hadoop2.7.tgz
export SPARK_HOME=$HOME/spark-2.2.1-bin-hadoop2.7
export PATH=$PATH:$SPARK_HOME/bin
 
# Start a Spark master
cd $SPARK_HOME
./sbin/start-master.sh

Télécharger le connecteur HDFS et créer des fichiers de configuration

Note

Pour les besoins de cet exemple, placez les fichiers JAR et de clés dans le répertoire de base de l'utilisateur courant. Pour les scénarios de production, vous placeriez plutôt ces fichiers dans un emplacement commun qui applique les autorisations appropriées (c'est-à-dire, pour qu'ils soient accessibles en lecture par l'utilisateur sous lequel Spark et Hive sont exécutés).

Téléchargez le connecteur HDFS dans l'instance de service et ajoutez les fichiers de configuration pertinents à l'aide de l'exemple de code suivant. Pour plus d'informations, voir Connecteur HDFS pour le stockage d'objets.

wget https://github.com/oracle/oci-hdfs-connector/releases/download/v2.9.2.1/oci-hdfs.zip
unzip oci-hdfs.zip -d oci-hdfs
 
cd $HOME
mkdir .oci
# Create or copy your API key into the $HOME/.oci directory
 
cd $SPARK_HOME/conf
# Create a core-site.xml (e.g. by transferring one you have, using vi etc.). Consult
# https://docs.oracle.com/iaas/Content/API/SDKDocs/hdfsconnector.htm#Properties
# for what this should look like
 
# Create a spark-defaults.conf file from the template
cp spark-defaults.conf.template spark-defaults.conf

Dans le fichier spark-defaults.conf, ajoutez les éléments suivants en bas :

spark.sql.hive.metastore.sharedPrefixes= shaded.oracle,com.oracle.bmc

Préparer les données

Pour les tests de données, nous utiliserons le jeu de données MovieLens.

  1. Téléchargez le dernier jeu de données à l'adresse https://grouplens.org/datasets/movielens/latest/. Assurez-vous de télécharger le petit jeu de données.
  2. Décompressez le fichier de téléchargement.
  3. Chargez le fichier movies.csv dans le seau du stockage d'objets.

Exécuter le test avec Spark Shell

Les données étant prêtes, nous pouvons maintenant lancer l'interpréteur de commandes de Spark pour les tester à l'aide d'un exemple de commande :

cd $SPARK_HOME
./bin/spark-shell
 
scala> sc.wholeTextFiles("oci://PipedUploadTest@sampletenancy/")
java.io.IOException: No FileSystem for scheme: oci

Vous recevez une erreur à ce stade, car le schéma du système oci:// file n'est pas disponible. Nous devons référencer le fichier JAR avant de démarrer l'interpréteur de commandes Spark. Voici un exemple pour ce faire :

./bin/spark-shell --jars $HOME/oci-hdfs/lib/oci-hdfs-full-1.2.7.jar --driver-class-path $HOME/oci-hdfs/lib/oci-hdfs-full-1.2.7.jar
 
scala> sc.wholeTextFiles("oci://PipedUploadTest@sampletenancy/")
res0: org.apache.spark.rdd.RDD[(String, String)] = oci://PipedUploadTest@sampletenancy/ MapPartitionsRDD[1] at wholeTextFiles at <console>:25
 
scala> sc.textFile("oci://PipedUploadTest@sampletenancy/movies.csv").take(20).foreach(println)
movieId,title,genres
1,Toy Story (1995),Adventure|Animation|Children|Comedy|Fantasy
2,Jumanji (1995),Adventure|Children|Fantasy
3,Grumpier Old Men (1995),Comedy|Romance
4,Waiting to Exhale (1995),Comedy|Drama|Romance
5,Father of the Bride Part II (1995),Comedy
6,Heat (1995),Action|Crime|Thriller
7,Sabrina (1995),Comedy|Romance
8,Tom and Huck (1995),Adventure|Children
9,Sudden Death (1995),Action
10,GoldenEye (1995),Action|Adventure|Thriller
11,"American President, The (1995)",Comedy|Drama|Romance
12,Dracula: Dead and Loving It (1995),Comedy|Horror
13,Balto (1995),Adventure|Animation|Children
14,Nixon (1995),Drama
15,Cutthroat Island (1995),Action|Adventure|Romance
16,Casino (1995),Crime|Drama
17,Sense and Sensibility (1995),Drama|Romance
18,Four Rooms (1995),Comedy
19,Ace Ventura: When Nature Calls (1995),Comedy

La commande a réussi. Nous pouvons nous connecter au stockage d'objets. Notez que si vous ne voulez pas transmettre l'argument --jars chaque fois que la commande est exécutée, vous pouvez copier le fichier JAR oci-hdfs-full dans le répertoire $SPARK_HOME/jars.

Démarrer le serveur Spark Thrift

Démarrez le serveur Spark Thrift sur le port 10015 et utilisez l'outil de ligne de commande Beeline pour établir une connexion JDBC, puis exécutez une interrogation de base, comme illustré ici :

cd $SPARK_HOME
./sbin/start-thriftserver.sh --hiveconf hive.server2.thrift.port=10015

Une fois le serveur Spark en cours d'exécution, nous pouvons lancer Beeline, comme indiqué ici :

cd $SPARK_HOME
./bin/beeline
Beeline version 1.2.1.spark2 by Apache Hive
beeline>

Vous pouvez ensuite vous connecter au serveur, comme indiqué ici :

Note

Pour les besoins de cet exemple, nous n'avons pas configuré de sécurité, de sorte que n'importe quel nom d'utilisateur et n'importe quel mot de passe sont acceptés. Pour les scénarios de production, vous ne procéderiez pas ainsi.
beeline> !connect jdbc:hive2://localhost:10015 testuser testpass
Connecting to jdbc:hive2://localhost:10015
log4j:WARN No appenders could be found for logger (org.apache.hive.jdbc.Utils).
log4j:WARN Please initialize the log4j system properly.
log4j:WARN See http://logging.apache.org/log4j/1.2/faq.html#noconfig for more info.
Connected to: Spark SQL (version 2.2.1)
Driver: Hive JDBC (version 1.2.1.spark2)
Transaction isolation: TRANSACTION_REPEATABLE_READ
0: jdbc:hive2://localhost:10015>

Si nous vérifions maintenant quelles tables existent, nous voyons le résultat suivant :

0: jdbc:hive2://localhost:10015> show tables;
+-----------+------------+--------------+--+
| database  | tableName  | isTemporary  |
+-----------+------------+--------------+--+
+-----------+------------+--------------+--+
No rows selected (0.724 seconds)

Aucune table n'existe actuellement. Toutefois, nous pouvons créer une table et la lier au fichier movies.csv que nous avons téléchargé et placé dans le seau de stockage d'objets, comme illustré ici :

0: jdbc:hive2://localhost:10015> create table test_table (movieId integer, title string, genres string) using csv options (path "oci://myBucket@myTenant/movies.csv", header "true", delimiter ",");
 
0: jdbc:hive2://localhost:10015> describe formatted test_table;
+-------------------------------+------------------------------------------------------------+----------+--+
|           col_name            |                         data_type                          | comment  |
+-------------------------------+------------------------------------------------------------+----------+--+
| movieId                       | int                                                        | NULL     |
| title                         | string                                                     | NULL     |
| genres                        | string                                                     | NULL     |
|                               |                                                            |          |
| # Detailed Table Information  |                                                            |          |
| Database                      | default                                                    |          |
| Table                         | test_table                                                 |          |
| Owner                         | opc                                                        |          |
| Created                       | Thu Mar 01 20:45:18 GMT 2018                               |          |
| Last Access                   | Thu Jan 01 00:00:00 GMT 1970                               |          |
| Type                          | EXTERNAL                                                   |          |
| Provider                      | csv                                                        |          |
| Table Properties              | [transient_lastDdlTime=1519937118]                         |          |
| Location                      | oci://PipedUploadTest@sampletenancy/movies.csv    |          |
| Serde Library                 | org.apache.hadoop.hive.serde2.lazy.LazySimpleSerDe         |          |
| InputFormat                   | org.apache.hadoop.mapred.SequenceFileInputFormat           |          |
| OutputFormat                  | org.apache.hadoop.hive.ql.io.HiveSequenceFileOutputFormat  |          |
| Storage Properties            | [delimiter=,, header=true, serialization.format=1]         |          |
+-------------------------------+------------------------------------------------------------+----------+--+

Notez que la table stocke ses données en externe dans le stockage d'objets et que les données sont accessibles à l'aide du connecteur HDFS (schéma du système de fichiers oci://). Maintenant que nous avons une table, nous pouvons l'interroger :

0: jdbc:hive2://localhost:10015> select * from test_table limit 10;
+----------+-------------------------------------+----------------------------------------------+--+
| movieId  |                title                |                    genres                    |
+----------+-------------------------------------+----------------------------------------------+--+
| 1        | Toy Story (1995)                    | Adventure|Animation|Children|Comedy|Fantasy  |
| 2        | Jumanji (1995)                      | Adventure|Children|Fantasy                   |
| 3        | Grumpier Old Men (1995)             | Comedy|Romance                               |
| 4        | Waiting to Exhale (1995)            | Comedy|Drama|Romance                         |
| 5        | Father of the Bride Part II (1995)  | Comedy                                       |
| 6        | Heat (1995)                         | Action|Crime|Thriller                        |
| 7        | Sabrina (1995)                      | Comedy|Romance                               |
| 8        | Tom and Huck (1995)                 | Adventure|Children                           |
| 9        | Sudden Death (1995)                 | Action                                       |
| 10       | GoldenEye (1995)                    | Action|Adventure|Thriller                    |
+----------+-------------------------------------+----------------------------------------------+--+