Use um JAR em um Jobdo Databricks

O arquivo Java ou formato de arquivo JAR é baseado no popular formato de arquivo ZIP e é usado para agregar muitos arquivos Java ou Scala em um. Usando a tarefa JAR, você pode garantir uma instalação rápida e confiável do código Java ou Scala em seu Job do Databricks. Este artigo fornece um exemplo de criação de um JAR e um Job que executa o pacote do aplicativo no JAR. Neste exemplo, você irá:

  • Crie o projeto JAR definindo um aplicativo de exemplo.

  • Empacote os arquivos de exemplo em um JAR.

  • Crie um Job para executar o JAR.

  • executar o Job e view os resultados.

Antes de começar

Você precisa do seguinte para concluir este exemplo:

  • Para Java JARs, o Java Development Kit (JDK).

  • Para Scala JARs, o JDK e o sbt.

passo 1: Crie 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.

passo 2: Criar o JAR

Conclua as instruções a seguir para usar Java ou Scala para criar o JAR.

Criar um Java JAR

  1. Na pasta databricks_jar_test , crie um arquivo chamado PrintArgs.java com o seguinte conteúdo:

    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) execução do programa compilado:

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

  5. Na pasta META-INF , crie um arquivo chamado MANIFEST.MF com o seguinte conteúdo. 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 endereço JAR:

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

    Observação

    Se você receber o erro no main manifest attribute, in PrintArgs.jar, certifique-se de adicionar uma nova linha ao final do arquivo MANIFEST.MF e tente criar e executar o JAR novamente.

  8. Faça upload de PrintArgs.jar para um volume. Consulte Fazer upload de arquivos para um volume do Unity Catalog.

Criar um Scala JAR

  1. Na pasta databricks_jar_test , crie um arquivo vazio chamado build.sbt com o seguinte conteúdo:

    ThisBuild / scalaVersion := "2.12.14"
    ThisBuild / organization := "com.example"
    
    lazy val PrintArgs = (project in file("."))
      .settings(
        name := "PrintArgs"
      )
    
  2. Na 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. Compile o programa:

    sbt compile
    
  5. (Opcional) execução do 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 endereço JAR:

    java -jar target/scala-2.12/PrintArgs-assembly-0.1.0-SNAPSHOT.jar Hello World!
    
    # Hello, World!
    
  9. Faça upload de PrintArgs-assembly-0.1.0-SNAPSHOT.jar para um volume. Consulte Fazer upload de arquivos para um volume do Unity Catalog.

passo 3. Crie um Job do Databricks para executar o JAR

  1. Vá para suas páginas de aterrissagem do Databricks e faça um dos seguintes:

    • Na barra lateral, clique em Ícone de trabalhos fluxo de trabalho e clique Botão Criar Job.

    • Na barra lateral, clique em Novo ícone Novo e selecione Job no menu.

  2. Na caixa de diálogo da tarefa que aparece na tab Tarefas , substitua Adicionar um nome para o Job pelo nome Job , 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. Para Tipo, selecione JAR.

  5. Para Main class, para este exemplo, insira PrintArgs para Java ou example.PrintArgs para Scala.

  6. Para clusterselecione um site compatível cluster. Consulte Java e Scala para obter suporte à biblioteca.

  7. Para bibliotecas dependentes, clique em + Adicionar.

  8. Na caixa de diálogo Add dependent library (Adicionar biblioteca dependente ), com Volumes (Volumes ) selecionado, digite o local em que o senhor carregou o JAR (PrintArgs.jar ou PrintArgs-assembly-0.1.0-SNAPSHOT.jar) no passo anterior em Volumes File Path (Caminho do arquivo do Volumes), ou filtre ou navegue para localizar o JAR. Selecione-o.

  9. Clique em Adicionar.

  10. Para Parâmetros, para este exemplo, insira ["Hello", "World!"].

  11. Clique em Adicionar.

passo 4: execute o Job e visualize os detalhes da execução Job

Clique botão de execução Agora para executar o fluxo de trabalho. Para visualizar os detalhes da execução, clique em Exibir execução no pop-up Execução acionada ou clique no link na coluna de horário de início da execução na exibição ExecuçõesJob .

Quando a execução for concluída, a saída será exibida no painel Saída , incluindo os argumentos passados para a tarefa.

Limites de tamanho de saída para trabalhos JAR

A saída Job , como a saída logs 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 como falha.

Para evitar encontrar esse limite, você pode impedir que stdout seja retornado do driver para Databricks definindo a configuração do spark.databricks.driver.disableScalaOutput Spark como true. Por default, o valor do sinalizador é false. O sinalizador controla a saída da célula para Scala JAR Job e Scala Notebook. Se o sinalizador estiver habilitado, o Spark não retornará os resultados da execução Job para o cliente. O sinalizador não afeta os dados gravados nos arquivos logsdos clusters . Databricks recomenda definir esse sinalizador apenas para clusters Job para Job JAR porque desabilita os resultados Notebook .

Recomendação: use o SparkContextcompartilhado

Como o Databricks é um serviço gerenciado, algumas alterações de código podem ser necessárias para garantir a execução correta do seu Apache Spark Job . Os programas JAR Job devem usar a API SparkContext compartilhada para obter o SparkContext. Como o Databricks inicializa o SparkContext, os programas que invocam new SparkContext() falharão. Para obter o SparkContext, use apenas o SparkContext compartilhado criado por Databricks:

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

Existem também vários métodos que você deve evitar ao usar o SparkContext compartilhado.

  • Não ligue para SparkContext.stop().

  • Não chame System.exit(0) ou sc.stop() no final do seu programa Main . Isso pode causar um comportamento indefinido.

Recomendação: use blocos try-finally para limpeza Job

Considere um JAR que consiste em duas partes:

  • jobBody() que contém a parte principal do Job.

  • jobCleanup() que deve ser executado após jobBody(), se essa função foi bem-sucedida ou retornou uma exceção.

Por exemplo, jobBody() cria tabelas e jobCleanup() descarta essas tabelas.

A maneira segura de garantir que o método de limpeza seja chamado é colocar um bloco try-finally no código:

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

Você não deve tentar limpar usando sys.addShutdownHook(jobCleanup) ou o seguinte código:

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

Devido à maneira como o tempo de vida dos contêineres Spark é gerenciado no Databricks, os hooks de desligamento não são executados de forma confiável.

Configurando os parâmetros do JAR Job

Você passa parâmetros para JAR Job com uma matriz de strings JSON. Veja o objeto spark_jar_task no corpo da solicitação passado para as operações Criar um novo Job (POST /jobs/create) na API Jobs. Para acessar esses parâmetros, inspecione o array String passado para sua função main .

gerenciar dependências da biblioteca

O driver Spark tem certas dependências de biblioteca que não podem ser substituídas. Se seu Job adicionar bibliotecas conflitantes, as dependências da biblioteca do driver Spark terão precedência.

Para obter a lista completa das dependências da biblioteca do driver, execute o seguinte comando em um Notebook anexado a um clusters configurado com a mesma versão do Spark (ou os clusters com o driver que você deseja examinar):

%sh
ls /databricks/jars

Quando você define dependências de biblioteca para JARs, Databricks recomenda listar Spark e Hadoop como provided dependências. 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>

Em 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 Scala correta para suas dependências com base na versão que você está executando.

Próximos passos

Para saber mais sobre como criar e executar Job do Databricks, consulte Criar e executar trabalhos do Databricks.