Partager via


Utiliser un JAR dans un travail Azure Databricks

Le format de fichier d’archive Java, ou [JAR](https://en.wikipedia.org/wiki/JAR_(file_format) est basé sur le format de fichier ZIP populaire et est utilisé pour regrouper de nombreux fichiers Java ou Scala en un seul. À l’aide de la tâche JAR, vous pouvez garantir une installation rapide et fiable du code Java ou Scala dans vos travaux Azure Databricks. Cet article fournit un exemple de création d’un fichier JAR et d’un travail qui exécute l’application empaquetée dans le fichier JAR. Dans cet exemple, vous allez :

  • Créez le projet JAR définissant un exemple d’application.
  • Regroupez les exemples de fichiers dans un fichier JAR.
  • Créez un travail pour exécuter le fichier JAR.
  • Exécutez le travail et affichez les résultats.

Avant de commencer

Les éléments suivants sont nécessaires pour effectuer cet exemple :

  • Pour les JAR Java, le kit de développement Java (JDK).
  • Pour les JAR Scala, le JDK et sbt.

Étape 1 : Créer un répertoire local pour l’exemple

Créez un répertoire local pour contenir l’exemple de code et les artefacts générés, par exemple databricks_jar_test.

Étape 2 : création du JAR

Suivez les instructions suivantes pour utiliser Java ou Scala pour créer le fichier JAR.

Créer un JAR Java

  1. Dans le dossier databricks_jar_test, créez un fichier nommé PrintArgs.java avec le contenu suivant :

    import java.util.Arrays;
    
    public class PrintArgs {
      public static void main(String[] args) {
        System.out.println(Arrays.toString(args));
      }
    }
    
  2. Compilez le fichier PrintArgs.java, ce qui crée le fichier PrintArgs.class :

    javac PrintArgs.java
    
  3. (Facultatif) Exécutez le programme compilé :

    java PrintArgs Hello World!
    
    # [Hello, World!]
    
  4. Dans le même dossier que les fichiers PrintArgs.java et PrintArgs.class, créez un dossier nommé META-INF.

  5. Dans le dossier META-INF, créez un fichier nommé MANIFEST.MF avec le contenu suivant. Veillez à ajouter une nouvelle ligne à la fin de ce fichier :

    Main-Class: PrintArgs
    
  6. À la racine du dossier databricks_jar_test, créez un fichier JAR nommé PrintArgs.jar :

    jar cvfm PrintArgs.jar META-INF/MANIFEST.MF *.class
    
  7. (Facultatif) Pour le test, à partir de la racine du dossier databricks_jar_test, exécutez le JAR :

    java -jar PrintArgs.jar Hello World!
    
    # [Hello, World!]
    

    Remarque

    Si vous obtenez l’erreur no main manifest attribute, in PrintArgs.jar, veillez à ajouter une nouvelle ligne à la fin du fichier MANIFEST.MF, puis essayez de créer et d’exécuter à nouveau le fichier JAR.

  8. Chargez PrintArgs.jar sur un volume. Consultez Charger des fichiers dans un volume Unity Catalog.

Créer un fichier JAR Scala

  1. Dans le dossier databricks_jar_test, créez un fichier vide nommé build.sbt avec le contenu suivant :

    ThisBuild / scalaVersion := "2.12.14"
    ThisBuild / organization := "com.example"
    
    lazy val PrintArgs = (project in file("."))
      .settings(
        name := "PrintArgs"
      )
    
  2. À partir du dossier databricks_jar_test, créez la structure de dossiers src/main/scala/example.

  3. Dans le dossier example, créez un fichier nommé PrintArgs.scala avec le contenu suivant :

    package example
    
    object PrintArgs {
      def main(args: Array[String]): Unit = {
        println(args.mkString(", "))
      }
    }
    
  4. Compilez le programme :

    sbt compile
    
  5. (Facultatif) Exécutez le programme compilé :

    sbt "run Hello World\!"
    
    # Hello, World!
    
  6. Dans le dossier databricks_jar_test/project, créez un fichier nommé assembly.sbt avec le contenu suivant :

    addSbtPlugin("com.eed3si9n" % "sbt-assembly" % "2.0.0")
    
  7. À partir de la racine du dossier databricks_jar_test, exécutez la commande assembly, qui génère un fichier JAR sous le dossier target :

    sbt assembly
    
  8. (Facultatif) Pour le test, à partir de la racine du dossier databricks_jar_test, exécutez le JAR :

    java -jar target/scala-2.12/PrintArgs-assembly-0.1.0-SNAPSHOT.jar Hello World!
    
    # Hello, World!
    
  9. Chargez PrintArgs-assembly-0.1.0-SNAPSHOT.jar sur un volume. Consultez Charger des fichiers dans un volume Unity Catalog.

Étape 3. Créer un travail Azure Databricks pour exécuter le fichier JAR

  1. Accédez à votre page d’accueil Azure Databricks et effectuez l’une des opérations suivantes :
    • Dans la barre latérale, cliquez sur Icône de flux de travail Workflows, puis sur bouton Créer un travail.
    • Dans la barre latérale, cliquez sur nouvelle icône Nouveau, puis sélectionnez Travail dans le menu.
  2. Dans la boîte de dialogue tâche qui s’affiche sous l’onglet Tâches , remplacez Ajouter un nom à votre travail... par votre nom de travail, par exemple JAR example.
  3. Pour Nom de la tâche, entrez un nom pour la tâche, par exemple java_jar_task pour Java ou scala_jar_task pour Scala.
  4. Pour Type, sélectionnez JAR.
  5. Pour Classe Main, pour cet exemple, entrez PrintArgs pour Java ou example.PrintArgs pour Scala.
  6. Pour Cluster, sélectionnez un cluster compatible. Consultez Prise en charge des bibliothèques Java et Scala.
  7. Pour Bibliothèques dépendantes, cliquez sur + Ajouter.
  8. Dans la boîte de dialogue Ajouter une bibliothèque dépendante, avec Volumes sélectionné, entrez l’emplacement où vous avez chargé le fichier JAR (PrintArgs.jar ou PrintArgs-assembly-0.1.0-SNAPSHOT.jar) à l’étape précédente dans Chemin d’accès au fichier Volumes, ou filtrez ou recherchez le fichier JAR. Sélectionnez-le.
  9. Cliquez sur Add.
  10. Pour Paramètres, pour cet exemple, entrez ["Hello", "World!"].
  11. Cliquez sur Add.

Étape 4 : Exécuter le travail et afficher les détails de l’exécution du travail

Cliquez sur le bouton Exécuter maintenant pour exécuter le flux de travail. Pour afficher les détails de l’exécution, cliquez sur Afficher l’exécution dans la fenêtre contextuelle Exécution déclenchée ou cliquez sur le lien dans la colonne Heure de début de l’exécution dans la vue Exécutions de travaux.

Une fois l’exécution terminée, la sortie s’affiche dans le panneau Sortie, y compris les arguments passés à la tâche.

Limites de taille de sortie pour les travaux JAR

La sortie des travaux, telle que la sortie de journal émise vers stdout, est soumise à une limite de taille de 20 Mo. Si la sortie totale a une taille supérieure, l’exécution est annulée et marquée comme ayant échoué.

Pour éviter de rencontrer cette limite, vous pouvez empêcher le renvoi de stdout du pilote à Azure Databricks en définissant la configuration Spark spark.databricks.driver.disableScalaOutput sur true. Par défaut, la valeur de l’indicateur est false. L’indicateur contrôle la sortie des cellules pour les travaux JAR Scala et les notebooks Scala. Si l’indicateur est activé, Spark ne renvoie pas les résultats de l’exécution du travail au client. L’indicateur n’affecte pas les données qui sont écrites dans les fichiers journaux du cluster. Databricks recommande de définir cet indicateur uniquement pour les clusters de travaux pour les travaux JAR, car il désactive les résultats du notebook.

Recommandation: utiliser le SparkContext partagé

Étant donné qu’Azure Databricks est un service géré, certaines modifications de code peuvent être nécessaires pour garantir que vos travaux Apache Spark s’exécutent correctement. Les programmes de travaux JAR doivent utiliser l’API SparkContext partagée pour accéder à SparkContext. Étant donné qu’Azure Databricks Initialise SparkContext, les programmes qui appellent new SparkContext() échouent. Pour obtenir SparkContext, utilisez uniquement le SparkContext partagé créé par Azure Databricks :

val goodSparkContext = SparkContext.getOrCreate()
val goodSparkSession = SparkSession.builder().getOrCreate()

Il existe également plusieurs méthodes que vous devez éviter lorsque vous utilisez le SparkContext partagé.

  • N’appelez pas SparkContext.stop().
  • N’appelez pas System.exit(0) ou sc.stop() à la fin de votre programme Main. Cela peut entraîner un comportement indéfini.

Recommandation : utiliser les blocs try-finally pour le nettoyage du travail

Imaginez un fichier JAR constitué de deux parties :

  • jobBody() qui contient la partie principale du travail.
  • jobCleanup() qui doit être exécuté après jobBody(), que cette fonction ait réussi ou ait retourné une exception.

Par exemple, jobBody() crée des tableaux et jobCleanup() dépose ces tableaux.

Le moyen le plus sûr pour s’assurer que la méthode de nettoyage est bien appelée consiste à placer un bloc try-finally dans le code :

try {
  jobBody()
} finally {
  jobCleanup()
}

Vous ne devez pas essayer de nettoyer à l’aide de sys.addShutdownHook(jobCleanup) ou du code suivant :

val cleanupThread = new Thread { override def run = jobCleanup() }
Runtime.getRuntime.addShutdownHook(cleanupThread)

En raison de la façon dont est gérée la durée de vie des conteneurs Spark dans Azure Databricks, les crochets d’arrêt ne sont pas exécutés de manière fiable.

Configuration des paramètres d’un travail JAR

Vous passez des paramètres à des travaux JAR avec un tableau de chaînes JSON. Consultez l'objet spark_jar_task dans le corps de la demande passé à l’opération Create a new job (Créer un travail) (POST /jobs/create) dans l’API Travaux. Pour accéder à ces paramètres, inspectez le tableau String passé dans votre fonction main.

Gérer les dépendances de bibliothèque

Le pilote Spark comporte certaines dépendances de bibliothèque qui ne peuvent pas être remplacées. Si votre travail ajoute des bibliothèques en conflit, les dépendances de bibliothèque de pilotes Spark sont prioritaires.

Pour obtenir la liste complète des dépendances de la bibliothèque de pilotes, exécutez la commande suivante dans un notebook attaché à un cluster configuré avec la même version de Spark (ou le cluster avec le pilote que vous souhaitez examiner) :

%sh
ls /databricks/jars

Lorsque vous définissez des dépendances de bibliothèque pour les fichiers JAR, Databricks recommande de répertorier Spark et Hadoop en tant que dépendances provided. Dans Maven, ajoutez Spark et Hadoop en tant que dépendances fournies :

<dependency>
  <groupId>org.apache.spark</groupId>
  <artifactId>spark-core_2.11</artifactId>
  <version>2.3.0</version>
  <scope>provided</scope>
</dependency>
<dependency>
  <groupId>org.apache.hadoop</groupId>
  <artifactId>hadoop-core</artifactId>
  <version>1.2.1</version>
  <scope>provided</scope>
</dependency>

Dans sbt, ajoutez Spark et Hadoop en tant que dépendances fournies :

libraryDependencies += "org.apache.spark" %% "spark-core" % "2.3.0" % "provided"
libraryDependencies += "org.apache.hadoop" %% "hadoop-core" % "1.2.1" % "provided"

Conseil

Spécifiez la version Scala appropriée à vos dépendances en fonction de la version que vous exécutez.

Étapes suivantes

Pour en savoir plus sur la création et l’exécution de projets Azure Databricks, voir Planifier et orchestrer des flux de travail.