Compartilhar via


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

  1. Da pasta databricks_jar_test, crie um arquivo chamado PrintArgs.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));
      }
    }
    
  2. Compile o arquivo PrintArgs.java, que cria o arquivo PrintArgs.class:

    javac PrintArgs.java
    
  3. (Opcional) Execute o programa compilado:

    java PrintArgs Hello World!
    
    # [Hello, World!]
    
  4. Na mesma pasta que os arquivos PrintArgs.java e PrintArgs.class, crie uma pasta chamada META-INF.

  5. Na pasta META-INF, crie um arquivo chamado MANIFEST.MF com os seguintes conteúdos. Certifique-se de adicionar uma nova linha no final deste arquivo:

    Main-Class: PrintArgs
    
  6. Na raiz da pasta databricks_jar_test, crie um JAR chamado PrintArgs.jar:

    jar cvfm PrintArgs.jar META-INF/MANIFEST.MF *.class
    
  7. (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 arquivo MANIFEST.MF e tente criar e executar o JAR novamente.

  8. Carregue PrintArgs.jar em um volume. Consulte Carregar arquivos em um volume do Catálogo do Unity.

Criar um JAR Scala

  1. Da pasta databricks_jar_test, crie um arquivo vazio chamado build.sbt com os seguintes conteúdos:

    ThisBuild / scalaVersion := "2.12.14"
    ThisBuild / organization := "com.example"
    
    lazy val PrintArgs = (project in file("."))
      .settings(
        name := "PrintArgs"
      )
    
  2. Da pasta databricks_jar_test, crie a estrutura de pastas src/main/scala/example.

  3. Na pasta example, crie um arquivo chamado PrintArgs.scala com o seguinte conteúdo:

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

    sbt compile
    
  5. (Opcional) Execute o programa compilado:

    sbt "run Hello World\!"
    
    # Hello, World!
    
  6. Na pasta databricks_jar_test/project, crie um arquivo chamado assembly.sbt com o seguinte conteúdo:

    addSbtPlugin("com.eed3si9n" % "sbt-assembly" % "2.0.0")
    
  7. Na raiz da pasta databricks_jar_test, execute o comando assembly, que gera um JAR na pasta target:

    sbt assembly
    
  8. (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!
    
  9. 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

  1. Vá para a página inicial do Azure Databricks e siga um destes procedimentos:
    • Na barra lateral, clique em Ícone de fluxos de trabalho Fluxos de trabalho e clique em botão Criar Trabalho.
    • Na barra lateral, clique em ícone Novo Novo e selecione Trabalho no menu.
  2. 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.
  3. Para Nome da tarefa, insira um nome para a tarefa, por exemplo java_jar_task para Java ou scala_jar_task para Scala.
  4. Em Tipo, selecione JAR.
  5. Em Classe principal, para este exemplo, insira PrintArgs para Java ou example.PrintArgs para Scala.
  6. Para Cluster, selecione um cluster compatível. Confira o suporte à biblioteca Java e Scala.
  7. Em bibliotecas dependentes, clique em + Adicionar.
  8. Na caixa de diálogo Adicionar biblioteca dependente, com Volumes selecionado, insira o local onde você carregou o JAR (PrintArgs.jar ou PrintArgs-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.
  9. Clique em Adicionar.
  10. Em Parâmetros, para este exemplo, insira ["Hello", "World!"].
  11. Clique em Adicionar.

Etapa 4: executar o trabalho e exibir os detalhes da execução do trabalho

Clique no Botão Executar 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) ou sc.stop() no final do programa Main. 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 de jobBody(), 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 Criar e executar trabalhos do Azure Databricks.