Usare un file JAR in un processo di Azure Databricks
Il formato di file Java o [JAR](https://en.wikipedia.org/wiki/JAR_(file_format) si basa sul formato di file ZIP più diffuso e viene usato per aggregare in un solo file multipli file Java o Scala. Usando l'attività JAR, è possibile garantire un'installazione rapida e affidabile del codice Java o Scala nei processi di Azure Databricks. Questo articolo fornisce un esempio di creazione di un file JAR e di un processo che esegue l'applicazione in pacchetto nel file JAR. Nel seguente esempio, si eseguirà quanto segue:
- Creare il progetto JAR che definisce un'applicazione di esempio.
- Aggregare i file di esempio in un file JAR.
- Per eseguire il file JAR creare un processo.
- Eseguire il processo e visualizzare i risultati.
Prima di iniziare
Per completare questo esempio, è necessario quanto segue:
- Per Java JAR, Java Development Kit (JDK).
- Per i JAR Scala, JDK e sbt.
Passaggio 1: Creare una directory locale per l'esempio
Creare una directory locale per contenere il codice di esempio e gli artefatti generati, ad esempio databricks_jar_test
.
Passaggio 2: Creare il JAR
Completare le istruzioni seguenti per usare Java o Scala per creare il file JAR.
Creare un Java JAR
Nella cartella
databricks_jar_test
creare un file denominatoPrintArgs.java
con il seguente contenuto:import java.util.Arrays; public class PrintArgs { public static void main(String[] args) { System.out.println(Arrays.toString(args)); } }
Compilare il file
PrintArgs.java
, che crea il filePrintArgs.class
:javac PrintArgs.java
(Facoltativo) Eseguire il programma compilato:
java PrintArgs Hello World! # [Hello, World!]
Nella stessa cartella dei file
PrintArgs.java
ePrintArgs.class
creare una cartella denominataMETA-INF
.Nella cartella
META-INF
creare un file denominatoMANIFEST.MF
con il seguente contenuto. Assicurarsi di aggiungere una nuova riga alla fine di questo file:Main-Class: PrintArgs
Dalla radice della cartella
databricks_jar_test
creare un file JAR denominatoPrintArgs.jar
:jar cvfm PrintArgs.jar META-INF/MANIFEST.MF *.class
(Facoltativo) Per testarlo, dalla radice della cartella
databricks_jar_test
, eseguire il file JAR:java -jar PrintArgs.jar Hello World! # [Hello, World!]
Nota
Se viene visualizzato l'errore
no main manifest attribute, in PrintArgs.jar
, assicurarsi di aggiungere una nuova riga alla fine del fileMANIFEST.MF
e quindi provare a creare ed eseguire di nuovo il file JAR.Caricare
PrintArgs.jar
in un volume. Vedere Caricamento file in un volume del catalogo Unity.
Creare un file JAR Scala
Nella cartella
databricks_jar_test
creare un file vuoto denominatobuild.sbt
con il seguente contenuto:ThisBuild / scalaVersion := "2.12.14" ThisBuild / organization := "com.example" lazy val PrintArgs = (project in file(".")) .settings( name := "PrintArgs" )
databricks_jar_test
Dalla cartella creare la strutturasrc/main/scala/example
di cartelle .Nella cartella
example
creare un file denominatoPrintArgs.scala
con il seguente contenuto:package example object PrintArgs { def main(args: Array[String]): Unit = { println(args.mkString(", ")) } }
Compilare il programma:
sbt compile
(Facoltativo) Eseguire il programma compilato:
sbt "run Hello World\!" # Hello, World!
Nella cartella
databricks_jar_test/project
creare un file denominatoassembly.sbt
con il seguente contenuto:addSbtPlugin("com.eed3si9n" % "sbt-assembly" % "2.0.0")
Dalla radice della cartella
databricks_jar_test
eseguire il comandoassembly
, che genera un file JAR nella cartellatarget
:sbt assembly
(Facoltativo) Per testarlo, dalla radice della cartella
databricks_jar_test
, eseguire il file JAR:java -jar target/scala-2.12/PrintArgs-assembly-0.1.0-SNAPSHOT.jar Hello World! # Hello, World!
Caricare
PrintArgs-assembly-0.1.0-SNAPSHOT.jar
in un volume. Vedere Caricamento file in un volume del catalogo Unity.
Passaggio 3. Creare un processo di Azure Databricks per eseguire il file JAR
- Passare alla pagina di destinazione di Azure Databricks ed eseguire una delle operazioni seguenti:
- Nella barra laterale, fare clic su Flussi di lavoro e quindi .
- Nella barra laterale, fare clic su Nuovo e selezionare Processo dal menu.
- Nella finestra di dialogo delle attività visualizzata nella scheda Attività sostituire Aggiungi un nome per il processo... con il nome del processo, ad esempio
JAR example
. - Per Nome attività immettere un nome per l'attività, ad esempio
java_jar_task
per Java oscala_jar_task
per Scala. - In Tipo selezionare JAR.
- Per Classe principale, per questo esempio, immettere
PrintArgs
per Java oexample.PrintArgs
per Scala. - Per Cluster selezionare un cluster compatibile. Vedere Supporto per le librerie Java e Scala.
- Per Librerie dipendenti fare clic su + Aggiungi.
- Nella finestra di dialogo Aggiungi libreria dipendente, con Volumi selezionati, immettere il percorso in cui è stato caricato il file JAR (
PrintArgs.jar
oPrintArgs-assembly-0.1.0-SNAPSHOT.jar
) nel passaggio precedente in Percorso file volumi oppure filtrare o cercare il file JAR. Selezionarlo. - Fare clic su Aggiungi.
- Per Parametri, per questo esempio, immettere
["Hello", "World!"]
. - Fare clic su Aggiungi.
Passaggio 4: Eseguire il processo e visualizzare i dettagli dell'esecuzione del processo
Fare clic su per eseguire il flusso di lavoro. Per visualizzare i dettagli dell'esecuzione, fare clic su Visualizza esecuzione nella finestra popup Esecuzione attivata oppure fare clic sul collegamento nella colonna Ora di inizio per l'esecuzione nella visualizzazioneesecuzioni del processo.
Al termine dell'esecuzione, l'output viene visualizzato nel pannello Output, inclusi gli argomenti passati all'attività.
Limiti delle dimensioni di output per i processi JAR
L'output del processo, ad esempio l'output del log generato in stdout, è soggetto a un limite di dimensioni di 20 MB. Se l'output totale ha dimensioni maggiori, l'esecuzione viene annullata e contrassegnata come non riuscita.
Per evitare di riscontrare questo limite, è possibile impedire che stdout venga restituito dal driver ad Azure Databricks impostando la configurazione di Spark spark.databricks.driver.disableScalaOutput
su true
. Per impostazione predefinita, il valore del flag è false
. Il flag controlla l'output della cella per i processi JAR scala e i notebook Scala. Se il flag è abilitato, Spark non restituisce i risultati dell'esecuzione del processo al client. Il flag non influisce sui dati scritti nei file di log del cluster. Databricks consiglia di impostare questo flag solo per i cluster automatizzati per i processi JAR, perché disabilita i risultati del notebook.
Raccomandazione: usare la condivisione SparkContext
Poiché Azure Databricks è un servizio gestito, potrebbero essere necessarie alcune modifiche al codice per garantire che i processi Apache Spark vengano eseguiti correttamente. I programmi di processo JAR devono usare l'API condivisa SparkContext
per ottenere SparkContext
. Poiché Azure Databricks inizializza SparkContext
, i programmi che richiamano new SparkContext()
avranno esito negativo. Per ottenere SparkContext
, usare solo l'oggetto condiviso SparkContext
creato da Azure Databricks:
val goodSparkContext = SparkContext.getOrCreate()
val goodSparkSession = SparkSession.builder().getOrCreate()
Esistono anche diversi metodi da evitare quando si usa l'oggetto condiviso SparkContext
.
- Non chiamare
SparkContext.stop()
. - Non chiamare
System.exit(0)
osc.stop()
alla fine del programmaMain
. Ciò potrebbe causare comportamenti inaspettati.
Raccomandazione: usare i blocchi try-finally
per la pulizia del processo
Si consideri un file JAR costituito da due parti:
jobBody()
che contiene la parte principale del processo.jobCleanup()
che deve essere eseguito dopojobBody()
, indipendentemente dal fatto che tale funzione abbia avuto esito positivo o restituito un'eccezione.
Ad esempio, jobBody()
crea tabelle e jobCleanup()
elimina tali tabelle.
Il modo sicuro per assicurarsi che venga chiamato il metodo di pulizia consiste nell'inserire un blocco try-finally
nel codice:
try {
jobBody()
} finally {
jobCleanup()
}
Non è consigliabile provare a eseguire la pulizia usando sys.addShutdownHook(jobCleanup)
o il codice seguente:
val cleanupThread = new Thread { override def run = jobCleanup() }
Runtime.getRuntime.addShutdownHook(cleanupThread)
A causa del modo in cui la durata dei contenitori Spark viene gestita in Azure Databricks, gli hook di arresto non vengono eseguiti in modo affidabile.
Configurazione dei parametri del processo JAR
I parametri passano ai processi JAR con una matrice di stringhe JSON. Vedere l'oggetto spark_jar_task
nel corpo della richiesta passato all'operazione Crea un nuovo processo (POST /jobs/create
) nell'API Processi. Per accedere a questi parametri, esaminare la matrice String
passata nella funzione main
.
Gestione delle dipendenze della libreria
Il driver Spark presenta alcune dipendenze della libreria che non possono essere sottoposte a override. Se il processo aggiunge librerie in conflitto, le dipendenze della libreria del driver Spark hanno la precedenza.
Per ottenere l'elenco completo delle dipendenze della libreria del driver, eseguire il comando seguente in un notebook collegato a un cluster configurato con la stessa versione di Spark (o il cluster con il driver da esaminare):
%sh
ls /databricks/jars
Quando si definiscono le dipendenze della libreria per i file JAR, Databricks consiglia di elencare Spark e Hadoop come provided
dipendenze. In Maven aggiungere Spark e Hadoop come dipendenze fornite:
<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>
In sbt
aggiungere Spark e Hadoop come dipendenze fornite:
libraryDependencies += "org.apache.spark" %% "spark-core" % "2.3.0" % "provided"
libraryDependencies += "org.apache.hadoop" %% "hadoop-core" % "1.2.1" % "provided"
Suggerimento
Specificare la versione di Scala corretta per le dipendenze in base alla versione in esecuzione.
Passaggi successivi
Per altre informazioni sulla creazione e l'esecuzione di processi di Azure Databricks, vedere Pianificare e orchestrare i flussi di lavoro.