Développement local d'applications Oracle Cloud Infrastructure Data Flow et déploiement vers le cloud
Oracle Cloud Infrastructure Data Flow est un service cloud Apache Spark entièrement géré. Il permet d'exécuter des applications Spark à n'importe quelle échelle, avec un minimum de tâches d'administration ou de configuration. Data Flow est idéal pour programmer des travaux de traitement en batch fiables de longue durée.
Vous pouvez développer des applications Spark sans être connecté au cloud. Vous pouvez rapidement les développer, les tester et les itérer sur votre ordinateur portable. Lorsqu'ils sont prêts, vous pouvez les déployer vers Data Flow sans avoir à les reconfigurer, à modifier le code ou à appliquer des profils de déploiement.
- La plupart des bibliothèques et du code source utilisés pour exécuter Data Flow sont masqués. Vous n'avez plus besoin de mettre en correspondance les versions de kit SDK Data Flow et vous ne rencontrez plus aucun conflit de dépendance tierce avec Data Flow.
- Les kits SDK sont compatibles avec Spark. Vous n'avez donc plus besoin de déplacer les dépendances tierces en conflit, ce qui vous permet de séparer votre application de vos bibliothèques afin d'obtenir des builds plus rapides, moins compliqués, plus petits et plus flexibles.
- Le nouveau fichier de modèle pom.xml télécharge et crée une copie quasi identique de Data Flow sur votre ordinateur local. Vous pouvez exécuter le débogueur par étape sur votre ordinateur local pour détecter et résoudre les problèmes avant d'exécuter votre application sur Data Flow. Vous pouvez les compiler et les exécuter sur les mêmes versions de bibliothèque que celles exécutées par Data Flow. Oracle peut rapidement décider si vous rencontrez un problème lié à Data Flow ou au code de votre application.
Avant de commencer
Avant de commencer à développer vos applications, procédez comme suit :
- Une connexion Oracle Cloud avec la fonction de clé d'API activée. Chargez votre utilisateur sous Identité /Utilisateurs et vérifiez que vous avez la possibilité de créer des clés d'API.
- Une clé d'API inscrite et déployée sur votre environnement local. Pour plus d'informations, reportez-vous à Inscription d'une clé d'API.
- Installation locale fonctionnelle d'Apache Spark 2.4, 3.0.2, 3.2.1 ou 3.5.0. Pour vérifier cet élément, exécutez spark-shell dans la CLI.
- Une installation d'Apache Maven. Les instructions et exemples utilisent Maven pour télécharger les dépendances dont vous avez besoin.
Avant de commencer, vérifiez la sécurité des exécutions dans Data Flow. Il utilise un jeton de délégation qui lui permet de réaliser des opérations cloud en votre nom. Tout ce que votre compte peut effectuer dans la console Oracle Cloud Infrastructure peut être réalisé par votre travail Spark à l'aide de Data Flow. En cas d'exécution en mode local, vous devez utiliser une clé d'API qui permet à l'application locale d'envoyer des demandes authentifiées à divers services Oracle Cloud Infrastructure.

Pour simplifier les choses, utilisez une clé d'API générée pour le même utilisateur que lors de la connexion à la console Oracle Cloud Infrastructure. Vos applications disposent ainsi des mêmes privilèges que si vous les exécutez localement ou dans Data Flow.
1. Concepts de développement local
- Personnaliser votre installation Spark locale avec des fichiers de bibliothèque Oracle Cloud Infrastructure, de sorte qu'elle ressemble à l'environnement d'exécution de Data Flow.
- Détectez l'emplacement d'exécution du code.
- Configurez le client HDFS Oracle Cloud Infrastructure de manière appropriée.
Pour que vous puissiez basculer en toute fluidité entre votre ordinateur et Data Flow, vous devez utiliser certaines versions de Spark, Scala et Python dans votre configuration locale. Ajoutez le fichier JAR du connecteur HDFS Oracle Cloud Infrastructure. Ajoutez également dix bibliothèques de dépendances à votre installation Spark, installées lors de l'exécution de votre application dans Data Flow. Les étapes ci-dessous vous indiquent comment télécharger et installer ces dix bibliothèques de dépendances.
Version de Spark | Version de Scala | Version de Python |
---|---|---|
3,5 | 2,12 | 3,11 |
3.2.1 | 2.12.15 | 3.8 |
3.0.2 | 2.12.10 | 3.6.8 |
2.4.4 | 2.11.12 | 3.6.8 |
CONNECTOR=com.oracle.oci.sdk:oci-hdfs-connector:3.3.4.1.4.2
mkdir -p deps
touch emptyfile
mvn install:install-file -DgroupId=org.projectlombok -DartifactId=lombok -Dversion=1.18.26 -Dpackaging=jar -Dfile=emptyfile
mvn org.apache.maven.plugins:maven-dependency-plugin:2.7:get -Dartifact=$CONNECTOR -Ddest=deps
mvn org.apache.maven.plugins:maven-dependency-plugin:2.7:get -Dartifact=$CONNECTOR -Ddest=deps -Dtransitive=true -Dpackaging=pom
mvn org.apache.maven.plugins:maven-dependency-plugin:2.7:copy-dependencies -f deps/*.pom -DoutputDirectory=.
echo 'sc.getConf.get("spark.home")' | spark-shell
scala> sc.getConf.get("spark.home")
res0: String = /usr/local/lib/python3.11/site-packages/pyspark
Dans cet exemple, le répertoire de base Spark vers lequel copier les fichiers de dépendance est le suivant :
/usr/local/lib/python3.11/site-packages/pyspark/jars
Copiez les fichiers de dépendance vers votre répertoire de base Spark.deps
contient de nombreux fichiers JAR, dont la plupart sont déjà disponibles dans l'installation Spark. Vous devez copier uniquement un sous-ensemble de ces fichiers JAR dans l'environnement Spark :bcpkix-jdk15to18-1.74.jar
bcprov-jdk15to18-1.74.jar
guava-32.0.1-jre.jar
jersey-media-json-jackson-2.35.jar
oci-hdfs-connector-3.3.4.1.4.2.jar
oci-java-sdk-addons-apache-configurator-jersey-3.34.0.jar
oci-java-sdk-common-*.jar
oci-java-sdk-objectstorage-extensions-3.34.0.jar
jersey-apache-connector-2.35.jar
oci-java-sdk-addons-apache-configurator-jersey-3.34.0.jar
jersey-media-json-jackson-2.35.jar
oci-java-sdk-objectstorage-generated-3.34.0.jar
oci-java-sdk-circuitbreaker-3.34.0.jar
resilience4j-circuitbreaker-1.7.1.jar
resilience4j-core-1.7.1.jar
vavr-match-0.10.2.jar
vavr-0.10.2.jar
Copiez-les à partir du répertoire deps
vers le sous-répertoire jars
identifié à l'étape 2.import com.oracle.bmc.hdfs.BmcFilesystem
Fichiers JAR déployés correctement
En cas d'erreur, vous avez placé les fichiers au mauvais endroit. Dans cet exemple, il y a une erreur :
Fichiers JAR déployés de façon incorrecte
- Vous pouvez utiliser la valeur de
spark.master
dans l'objetSparkConf
, définie sur k8s ://https://kubernetes.default.svc:443 lors de l'exécution dans Data Flow. - La variable d'environnement
HOME
est définie sur/home/dataflow
lors de l'exécution dans Data Flow.
Dans les applications PySpark, un objet SparkConf
récemment créé est vide. Pour consulter les valeurs correctes, utilisez la méthode getConf
de la classe SparkContext
en cours d'exécution.
Environnement de lancement | Paramètre spark.master |
---|---|
Data Flow |
|
spark-submit local | spark.master: local[*] $HOME : variable |
Eclipse | Non défini $HOME : variable |
Lorsque vous êtes en cours d'exécution dans Data Flow, ne modifiez pas la valeur de
spark.master
. Dans ce cas, votre travail n'utilise pas toutes les ressources que vous avez provisionnées. Lorsque votre application est exécutée dans Data Flow, le connecteur HDFS Oracle Cloud Infrastructure est configuré automatiquement. En cas d'exécution locale, vous devez le configurer vous-même en définissant ses propriétés de configuration.
Au minimum, vous devez mettre à jour votre objet SparkConf
afin de définir des valeurs pour fs.oci.client.auth.fingerprint
, fs.oci.client.auth.pemfilepath
, fs.oci.client.auth.tenantId
, fs.oci.client.auth.userId
et fs.oci.client.hostname
.
Si votre clé d'API comporte une phrase de passe, vous devez définir fs.oci.client.auth.passphrase
.
Ces variables peuvent être définies après la création de la session. Dans votre environnement de programmation, utilisez les kits SDK respectifs pour charger correctement votre configuration de clé d'API.
ConfigFileAuthenticationDetailsProvider
comme il convient :import com.oracle.bmc.auth.ConfigFileAuthenticationDetailsProvider;
import com.oracle.bmc.ConfigFileReader;
//If your key is encrypted call setPassPhrase:
ConfigFileAuthenticationDetailsProvider authenticationDetailsProvider = new ConfigFileAuthenticationDetailsProvider(ConfigFileReader.DEFAULT_FILE_PATH, "<DEFAULT>");
configuration.put("fs.oci.client.auth.tenantId", authenticationDetailsProvider.getTenantId());
configuration.put("fs.oci.client.auth.userId", authenticationDetailsProvider.getUserId());
configuration.put("fs.oci.client.auth.fingerprint", authenticationDetailsProvider.getFingerprint());
String guessedPath = new File(configurationFilePath).getParent() + File.separator + "oci_api_key.pem";
configuration.put("fs.oci.client.auth.pemfilepath", guessedPath);
// Set the storage endpoint:
String region = authenticationDetailsProvider.getRegion().getRegionId();
String hostName = MessageFormat.format("https://objectstorage.{0}.oraclecloud.com", new Object[] { region });
configuration.put("fs.oci.client.hostname", hostName);
oci.config.from_file
comme il convient :import os
from pyspark import SparkConf, SparkContext
from pyspark.sql import SparkSession
# Check to see if we're in Data Flow or not.
if os.environ.get("HOME") == "/home/dataflow":
spark_session = SparkSession.builder.appName("app").getOrCreate()
else:
conf = SparkConf()
oci_config = oci.config.from_file(oci.config.DEFAULT_LOCATION, "<DEFAULT>")
conf.set("fs.oci.client.auth.tenantId", oci_config["tenancy"])
conf.set("fs.oci.client.auth.userId", oci_config["user"])
conf.set("fs.oci.client.auth.fingerprint", oci_config["fingerprint"])
conf.set("fs.oci.client.auth.pemfilepath", oci_config["key_file"])
conf.set(
"fs.oci.client.hostname",
"https://objectstorage.{0}.oraclecloud.com".format(oci_config["region"]),
)
spark_builder = SparkSession.builder.appName("app")
spark_builder.config(conf=conf)
spark_session = spark_builder.getOrCreate()
spark_context = spark_session.sparkContext
Dans SparkSQL, la configuration est gérée différemment. Ces paramètres sont transmis à l'aide du commutateur --hiveconf
. Pour exécuter des requêtes Spark SQL, utilisez un script de wrapper semblable à l'exemple. Lorsque vous exécutez votre script dans Data Flow, ces paramètres sont automatiquement définis pour vous.
#!/bin/sh
CONFIG=$HOME/.oci/config
USER=$(egrep ' user' $CONFIG | cut -f2 -d=)
FINGERPRINT=$(egrep ' fingerprint' $CONFIG | cut -f2 -d=)
KEYFILE=$(egrep ' key_file' $CONFIG | cut -f2 -d=)
TENANCY=$(egrep ' tenancy' $CONFIG | cut -f2 -d=)
REGION=$(egrep ' region' $CONFIG | cut -f2 -d=)
REMOTEHOST="https://objectstorage.$REGION.oraclecloud.com"
spark-sql \
--hiveconf fs.oci.client.auth.tenantId=$TENANCY \
--hiveconf fs.oci.client.auth.userId=$USER \
--hiveconf fs.oci.client.auth.fingerprint=$FINGERPRINT \
--hiveconf fs.oci.client.auth.pemfilepath=$KEYFILE \
--hiveconf fs.oci.client.hostname=$REMOTEHOST \
-f script.sql
Les exemples ci-dessus modifient uniquement la façon dont vous créez votre contexte Spark. Rien d'autre dans votre application Spark ne doit être modifié, de sorte que vous puissiez développer d'autres aspects de celle-ci comme vous le feriez habituellement. Lorsque vous déployez votre application Spark vers Data Flow, vous n'avez pas besoin de modifier le code ou la configuration.
2. Création de fichiers Fat JAR pour les applications Java
Les applications Java et Scala doivent généralement inclure plus de dépendances dans un fichier JAR appelé "fichier Fat JAR".
Si vous utilisez Maven, vous pouvez employer le module d'extension Shade
à cette fin. Les exemples suivants proviennent de fichiers Maven pom.xml
. Vous pouvez les utiliser comme point de départ pour votre projet. Lorsque vous créez votre application, les dépendances sont automatiquement téléchargées et insérées dans votre environnement d'exécution.
Si vous utilisez Spark 3.5.0 ou 3.2.1, ce chapitre ne s'applique pas. Reportez-vous plutôt au chapitre 2. Gestion des dépendances Java pour les applications Apache Spark dans Data Flow.
Cette partie de fichier pom.xml inclut les versions correctes de bibliothèque Oracle Cloud Infrastructure et Spark pour Data Flow (Spark 3.0.2). Elle cible Java 8 et ombre les fichiers de classe en conflit courants.
<properties>
<oci-java-sdk-version>1.25.2</oci-java-sdk-version>
</properties>
<dependencies>
<dependency>
<groupId>com.oracle.oci.sdk</groupId>
<artifactId>oci-hdfs-connector</artifactId>
<version>3.2.1.3</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>com.oracle.oci.sdk</groupId>
<artifactId>oci-java-sdk-core</artifactId>
<version>${oci-java-sdk-version}</version>
</dependency>
<dependency>
<groupId>com.oracle.oci.sdk</groupId>
<artifactId>oci-java-sdk-objectstorage</artifactId>
<version>${oci-java-sdk-version}</version>
</dependency>
<!-- spark -->
<dependency>
<groupId>org.apache.spark</groupId>
<artifactId>spark-core_2.12</artifactId>
<version>3.0.2</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.apache.spark</groupId>
<artifactId>spark-sql_2.12</artifactId>
<version>3.0.2</version>
<scope>provided</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.0</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.22.0</version>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>3.1.1</version>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>shade</goal>
</goals>
</execution>
</executions>
<configuration>
<transformers>
<transformer
implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
<mainClass>example.Example</mainClass>
</transformer>
</transformers>
<filters>
<filter>
<artifact>*:*</artifact>
<excludes>
<exclude>META-INF/*.SF</exclude>
<exclude>META-INF/*.DSA</exclude>
<exclude>META-INF/*.RSA</exclude>
</excludes>
</filter>
</filters>
<relocations>
<relocation>
<pattern>com.oracle.bmc</pattern>
<shadedPattern>shaded.com.oracle.bmc</shadedPattern>
<includes>
<include>com.oracle.bmc.**</include>
</includes>
<excludes>
<exclude>com.oracle.bmc.hdfs.**</exclude>
</excludes>
</relocation>
</relocations>
<artifactSet>
<excludes>
<exclude>org.bouncycastle:bcpkix-jdk15on</exclude>
<exclude>org.bouncycastle:bcprov-jdk15on</exclude>
<!-- Including jsr305 in the shaded jar causes a SecurityException
due to signer mismatch for class "javax.annotation.Nonnull" -->
<exclude>com.google.code.findbugs:jsr305</exclude>
</excludes>
</artifactSet>
</configuration>
</plugin>
</plugins>
</build>
Cette partie pom.xml
inclut les versions correctes de bibliothèque Oracle Cloud Infrastructure et Spark pour Data Flow ( Spark 2.4.4). Elle cible Java 8 et ombre les fichiers de classe en conflit courants.
<properties>
<oci-java-sdk-version>1.15.4</oci-java-sdk-version>
</properties>
<dependencies>
<dependency>
<groupId>com.oracle.oci.sdk</groupId>
<artifactId>oci-hdfs-connector</artifactId>
<version>2.7.7.3</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>com.oracle.oci.sdk</groupId>
<artifactId>oci-java-sdk-core</artifactId>
<version>${oci-java-sdk-version}</version>
</dependency>
<dependency>
<groupId>com.oracle.oci.sdk</groupId>
<artifactId>oci-java-sdk-objectstorage</artifactId>
<version>${oci-java-sdk-version}</version>
</dependency>
<!-- spark -->
<dependency>
<groupId>org.apache.spark</groupId>
<artifactId>spark-core_2.12</artifactId>
<version>2.4.4</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.apache.spark</groupId>
<artifactId>spark-sql_2.12</artifactId>
<version>2.4.4</version>
<scope>provided</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.0</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.22.0</version>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>3.1.1</version>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>shade</goal>
</goals>
</execution>
</executions>
<configuration>
<transformers>
<transformer
implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
<mainClass>example.Example</mainClass>
</transformer>
</transformers>
<filters>
<filter>
<artifact>*:*</artifact>
<excludes>
<exclude>META-INF/*.SF</exclude>
<exclude>META-INF/*.DSA</exclude>
<exclude>META-INF/*.RSA</exclude>
</excludes>
</filter>
</filters>
<relocations>
<relocation>
<pattern>com.oracle.bmc</pattern>
<shadedPattern>shaded.com.oracle.bmc</shadedPattern>
<includes>
<include>com.oracle.bmc.**</include>
</includes>
<excludes>
<exclude>com.oracle.bmc.hdfs.**</exclude>
</excludes>
</relocation>
</relocations>
<artifactSet>
<excludes>
<exclude>org.bouncycastle:bcpkix-jdk15on</exclude>
<exclude>org.bouncycastle:bcprov-jdk15on</exclude>
<!-- Including jsr305 in the shaded jar causes a SecurityException
due to signer mismatch for class "javax.annotation.Nonnull" -->
<exclude>com.google.code.findbugs:jsr305</exclude>
</excludes>
</artifactSet>
</configuration>
</plugin>
</plugins>
</build>
3. Test local de votre application
Avant de déployer votre application, vous pouvez la tester localement pour vous assurer qu'elle fonctionne. Trois techniques vous permettent de sélectionner celle qui fonctionne le mieux pour vous. Ces exemples supposent que l'artefact d'application est nommé application.jar
(pour Java) ou application.py
(pour Python).
- Data Flow masque la plupart du code source et des bibliothèques qu'il utilise pour l'exécution. Les versions du kit SDK Data Flow n'ont donc plus besoin d'être mises en correspondance et les conflits de dépendance tierce avec Data Flow ne doivent pas se produire.
- Spark a été mis à niveau afin que les kits SDK OCI soient désormais compatibles avec lui. Cela signifie que les dépendances tierces conflictuelles n'ont pas besoin d'être déplacées, de sorte que les bibliothèques d'applications et de bibliothèques peuvent être séparées pour des builds plus rapides, moins compliqués, plus petits et plus flexibles.
- Le nouveau modèle de fichier pom.xml télécharge et crée une copie de Data Flow presque identique sur l'ordinateur local d'un développeur. De ce fait :
- Les développeurs peuvent exécuter le débogueur d'étape sur leur ordinateur local pour détecter et résoudre rapidement les problèmes avant de les exécuter sur Data Flow.
- Les développeurs peuvent les compiler et les exécuter sur les mêmes versions de bibliothèque que celles exécutées par Data Flow. L'équipe Data Flow peut donc décider rapidement si un problème est lié à Data Flow ou au code de l'application.
Méthode 1 : exécution à partir de votre IDE
Si vous avez développé un IDE tel qu'Eclipse, vous n'avez pas besoin de faire autre chose que de cliquer sur Exécuter et de sélectionner la classe principale appropriée.
Lors de l'exécution, il est normal que Spark génère des messages d'avertissement dans la console. Vous savez ainsi que Spark est en cours d'appel.
Méthode 2 : exécution de PySpark à partir de la ligne de commande
python3 application.py
$ python3 example.py
Warning: Ignoring non-Spark config property: fs.oci.client.hostname
Warning: Ignoring non-Spark config property: fs.oci.client.auth.fingerprint
Warning: Ignoring non-Spark config property: fs.oci.client.auth.tenantId
Warning: Ignoring non-Spark config property: fs.oci.client.auth.pemfilepath
Warning: Ignoring non-Spark config property: fs.oci.client.auth.userId
20/08/01 06:52:00 WARN Utils: Your hostname resolves to a loopback address: 127.0.0.1; using 192.168.1.41 instead (on interface en0)
20/08/01 06:52:00 WARN Utils: Set SPARK_LOCAL_IP if you need to bind to another address
20/08/01 06:52:01 WARN NativeCodeLoader: Unable to load native-hadoop library for your platform... using builtin-java classes where applicable
Les avertissements sur les propriétés de configuration non Spark sont normaux si vous configurez le pilote HDFS Oracle Cloud Infrastructure en fonction de votre profil de configuration.Méthode 3 : utilisation de spark-submit
L'utilitaire spark-submit
est inclus dans votre distribution Spark. Utilisez cette méthode dans certaines situations, par exemple, lorsqu'une application PySpark requiert des fichiers JAR supplémentaires.
spark-submit
:spark-submit --class example.Example example.jar
Étant donné que vous devez fournir le nom de classe principale à Data Flow, ce code est un bon moyen de vérifier que vous utilisez le nom de classe correct. Gardez en tête que les noms de classe font la distinction entre les majuscules et les minuscules.
spark-submit
pour exécuter une application PySpark nécessitant des fichiers JAR Oracle JDBC :
spark-submit \
--jars java/oraclepki-18.3.jar,java/ojdbc8-18.3.jar,java/osdt_cert-18.3.jar,java/ucp-18.3.jar,java/osdt_core-18.3.jar \
example.py
4. Déploiement de l'application
- Copiez l'artefact d'application ( fichier
jar
, script Python ou script SQL) vers Oracle Cloud Infrastructure Object Storage. - Si votre application Java comporte des dépendances qui ne sont pas fournies par Data Flow, n'oubliez pas de copier le fichier
jar
d'assemblage. - Créez une application Data Flow qui référence cet artefact dans Oracle Cloud Infrastructure Object Storage.
Après l'étape 3, vous pouvez exécuter l'application autant de fois que vous le souhaitez. Pour plus d'informations, le tutoriel Introduction à Oracle Cloud Infrastructure Data Flow vous guide tout au long de ce processus étape par étape.
Etapes suivantes
Vous savez désormais comment développer vos applications localement et les déployer vers Data Flow.