Usar um JAR em um trabalho do Azure Databricks
O arquivo Java ou [JAR](https://en.wikipedia.org/wiki/JAR_(file_format) é baseado no formato de arquivo ZIP popular e é usado para agregar muitos arquivos Java ou Scala em um. Usando a tarefa JAR, você pode garantir a instalação rápida e confiável do código Java ou Scala em seus trabalhos do Azure Databricks. Este artigo fornece um exemplo de criação de um JAR e um trabalho que executa o aplicativo empacotado no JAR. Neste exemplo, você vai:
- Criar o projeto JAR definindo um aplicativo de exemplo.
- Empacotar os arquivos de exemplo em um JAR.
- Criar um trabalho para executar o JAR.
- Executará o trabalho e verá os resultados.
Antes de começar
Você precisa dos seguintes itens para concluir este exemplo:
- Para JARs Java, o JDK (Java Development Kit).
- Para JARs Scala, o JDK e o sbt.
Etapa 1: criar um diretório local para o exemplo
Crie um diretório local para conter o código de exemplo e os artefatos gerados, por exemplo, databricks_jar_test
.
Etapa 2: criar o JAR
Conclua as instruções a seguir para usar o Java ou Scala para criar o JAR.
Criar um JAR Java
Da pasta
databricks_jar_test
, crie um arquivo chamadoPrintArgs.java
com os seguintes conteúdos:import java.util.Arrays; public class PrintArgs { public static void main(String[] args) { System.out.println(Arrays.toString(args)); } }
Compile o arquivo
PrintArgs.java
, que cria o arquivoPrintArgs.class
:javac PrintArgs.java
(Opcional) Execute o programa compilado:
java PrintArgs Hello World! # [Hello, World!]
Na mesma pasta que os arquivos
PrintArgs.java
ePrintArgs.class
, crie uma pasta chamadaMETA-INF
.Na pasta
META-INF
, crie um arquivo chamadoMANIFEST.MF
com os seguintes conteúdos. Certifique-se de adicionar uma nova linha no final deste arquivo:Main-Class: PrintArgs
Na raiz da pasta
databricks_jar_test
, crie um JAR chamadoPrintArgs.jar
:jar cvfm PrintArgs.jar META-INF/MANIFEST.MF *.class
(Opcional) Para testá-lo, na raiz da pasta
databricks_jar_test
, execute o JAR:java -jar PrintArgs.jar Hello World! # [Hello, World!]
Observação
Se você receber o erro
no main manifest attribute, in PrintArgs.jar
, adicione uma nova linha ao final do arquivoMANIFEST.MF
e tente criar e executar o JAR novamente.Carregue
PrintArgs.jar
em um volume. Consulte Carregar arquivos em um volume do Catálogo do Unity.
Criar um JAR Scala
Da pasta
databricks_jar_test
, crie um arquivo vazio chamadobuild.sbt
com os seguintes conteúdos:ThisBuild / scalaVersion := "2.12.14" ThisBuild / organization := "com.example" lazy val PrintArgs = (project in file(".")) .settings( name := "PrintArgs" )
Da pasta
databricks_jar_test
, crie a estrutura de pastassrc/main/scala/example
.Na pasta
example
, crie um arquivo chamadoPrintArgs.scala
com o seguinte conteúdo:package example object PrintArgs { def main(args: Array[String]): Unit = { println(args.mkString(", ")) } }
Compilar o programa:
sbt compile
(Opcional) Execute o programa compilado:
sbt "run Hello World\!" # Hello, World!
Na pasta
databricks_jar_test/project
, crie um arquivo chamadoassembly.sbt
com o seguinte conteúdo:addSbtPlugin("com.eed3si9n" % "sbt-assembly" % "2.0.0")
Na raiz da pasta
databricks_jar_test
, execute o comandoassembly
, que gera um JAR na pastatarget
:sbt assembly
(Opcional) Para testá-lo, na raiz da pasta
databricks_jar_test
, execute o JAR:java -jar target/scala-2.12/PrintArgs-assembly-0.1.0-SNAPSHOT.jar Hello World! # Hello, World!
Carregue
PrintArgs-assembly-0.1.0-SNAPSHOT.jar
em um volume. Consulte Carregar arquivos em um volume do Catálogo do Unity.
Etapa 3. Criar um trabalho do Azure Databricks para executar o JAR
- Vá para a página inicial do Azure Databricks e siga um destes procedimentos:
- Na barra lateral, clique em Fluxos de trabalho e clique em .
- Na barra lateral, clique em Novo e selecione Trabalho no menu.
- Na caixa de diálogo da tarefa exibida na guia Tarefas, substitua Adicionar um nome para seu trabalho... com seu nome de trabalho, por exemplo
JAR example
. - Para Nome da tarefa, insira um nome para a tarefa, por exemplo
java_jar_task
para Java ouscala_jar_task
para Scala. - Em Tipo, selecione JAR.
- Em Classe principal, para este exemplo, insira
PrintArgs
para Java ouexample.PrintArgs
para Scala. - Para Cluster, selecione um cluster compatível. Confira o suporte à biblioteca Java e Scala.
- Em bibliotecas dependentes, clique em + Adicionar.
- Na caixa de diálogo Adicionar biblioteca dependente, com Volumes selecionado, insira o local onde você carregou o JAR (
PrintArgs.jar
ouPrintArgs-assembly-0.1.0-SNAPSHOT.jar
) na etapa anterior no Caminho do arquivo de volumes, ou filtre ou navegue para encontrar o JAR. Selecione-a. - Clique em Adicionar.
- Em Parâmetros, para este exemplo, insira
["Hello", "World!"]
. - Clique em Adicionar.
Etapa 4: executar o trabalho e exibir os detalhes da execução do trabalho
Clique no agora para executar o fluxo de trabalho. Para exibir detalhes da execução, clique em Exibir execução no item pop-up da Execução disparada ou clique no link na coluna Hora de início da execução na exibição de execuções de trabalho.
Quando a execução é concluída, a saída é exibida no painel Saída, incluindo os argumentos passados para a tarefa.
Limites de tamanho de saída para trabalhos JAR
A saída do trabalho, como a saída de log emitida para stdout, está sujeita a um limite de tamanho de 20 MB. Se a saída total tiver um tamanho maior, a execução será cancelada e marcada com falha.
Para evitar que chegue nesse limite, você pode impedir que o stdout seja retornado do driver para o Azure Databricks configurando spark.databricks.driver.disableScalaOutput
do Spark como true
. Por padrão, o valor do sinalizador é false
. O sinalizador controla a saída da célula para os trabalhos do JAR do Scala e os notebooks do Scala. Se o sinalizador estiver habilitado, o Spark não retornará os resultados de execução do trabalho para o cliente. O sinalizador não afeta os dados que são gravados nos arquivos de log do cluster. O Databricks recomenda definir esse sinalizador apenas para clusters de trabalho para trabalhos JAR porque desabilita os resultados do notebook.
Recomendação: usar o SparkContext
compartilhado
Como o Azure Databricks é um serviço gerenciado, algumas alterações de código podem ser necessárias para garantir que os trabalhos do Apache Spark sejam executados corretamente. Os programas de trabalho JAR precisam usar a API compartilhada SparkContext
para obter o SparkContext
. Como o Azure Databricks Inicializa o SparkContext
, os programas que invocarem new SparkContext()
falharão. Para obter o SparkContext
, use somente o SparkContext
compartilhado criado pelo Azure Databricks:
val goodSparkContext = SparkContext.getOrCreate()
val goodSparkSession = SparkSession.builder().getOrCreate()
Também há vários métodos que você deve evitar ao usar o SparkContext
compartilhado.
- Não chame
SparkContext.stop()
. - Não chame
System.exit(0)
ousc.stop()
no final do programaMain
. Isso pode causar um comportamento indefinido.
Recomendação: usar blocos try-finally
para limpeza de trabalho
Considere um JAR que consiste em duas partes:
jobBody()
, que contém a parte principal do trabalho.jobCleanup()
, que deve ser executado depois dejobBody()
, independentemente de a função ter êxito ou retornar uma exceção.
Por exemplo, jobBody()
cria tabelas e jobCleanup()
remove essas tabelas.
A maneira segura de garantir que o método de limpeza será chamado é colocar um bloco try-finally
no código:
try {
jobBody()
} finally {
jobCleanup()
}
Você não deve tentar limpar usando sys.addShutdownHook(jobCleanup)
o ou o código abaixo:
val cleanupThread = new Thread { override def run = jobCleanup() }
Runtime.getRuntime.addShutdownHook(cleanupThread)
Devido à maneira como o tempo de vida dos contêineres do Spark é gerenciado no Azure Databricks, os ganchos de desligamento não são executados de forma confiável.
Configurar parâmetros de trabalho JAR
Você transmite parâmetros a trabalhos JAR com uma matriz de cadeia de caracteres JSON. Confira o objeto spark_jar_task
no corpo da solicitação transmitido à operação Criar um trabalho (POST /jobs/create
) na API de Trabalhos. Para acessar esses parâmetros, inspecione a matriz String
transmitida na sua função main
.
Gerenciar dependências da biblioteca
O driver do Spark tem determinadas dependências de biblioteca que não podem ser substituídas. Se o trabalho adicionar bibliotecas conflitantes, as dependências da biblioteca de driver do Spark terão precedência.
Para obter a lista completa das dependências da biblioteca de driver, execute o seguinte comando em um notebook anexado a um cluster configurado com a mesma versão do Spark (ou o cluster com o driver que você deseja examinar):
%sh
ls /databricks/jars
Quando você define dependências de biblioteca para JARs, o Databricks recomenda listar o Spark e o Hadoop como dependências provided
. No Maven, adicione Spark e Hadoop como dependências fornecidas:
<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>
No sbt
, adicione Spark e Hadoop como dependências fornecidas:
libraryDependencies += "org.apache.spark" %% "spark-core" % "2.3.0" % "provided"
libraryDependencies += "org.apache.hadoop" %% "hadoop-core" % "1.2.1" % "provided"
Dica
Especifique a versão do Scala correta para suas dependências com base na versão que você está executando.
Próximas etapas
Para saber mais sobre como criar e executar trabalhos do Azure Databricks, confira Agendar e orquestrar fluxos de trabalho.