Use um JAR em um Databricks Job

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

  • Crie o projeto JAR que define um aplicativo de exemplo.

  • Agrupe os arquivos de exemplo em um JAR.

  • Criar um Job para executar o JAR.

  • Execute o job e veja os resultados.

Antes de começar

O senhor precisa dos seguintes itens para concluir este exemplo:

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

  • Para JARs do Scala, o JDK e o sbt.

passo 1: Crie um diretório local para o exemplo

Crie um diretório local para armazenar o código de exemplo e os artefatos gerados, por exemplo, databricks_jar_test.

passo 2: Criar o JAR

Siga 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. Compilar o arquivo PrintArgs.java, que cria o arquivo PrintArgs.class:

    javac PrintArgs.java
    
  3. (Opcional) executar o 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. Não se esqueça de adicionar uma nova linha no final desse 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 o senhor receber o erro no main manifest attribute, in PrintArgs.jar, certifique-se de adicionar uma nova linha ao final do arquivo MANIFEST.MF e, em seguida, 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 JAR do Scala

  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. A partir 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) executar 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 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. Acesse o site Databricks páginas de aterrissagem e faça uma das seguintes ações:

    • Na barra lateral, clique em fluxo de trabalho Icon fluxo de trabalho e clique em Botão criar job.

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

  2. Na caixa de diálogo da tarefa que aparece na tarefa tab, substitua Add a name for your Job (Adicionar um nome para o trabalho ) pelo nome do trabalho, por exemplo, JAR example.

  3. Para o nome da tarefa, digite um nome para a tarefa, por exemplo, java_jar_task para Java, ou scala_jar_task para Scala.

  4. Para Type, selecione JAR.

  5. Para a classe Main, neste exemplo, digite PrintArgs para Java ou example.PrintArgs para Scala.

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

  7. Para Biblioteca dependente, clique em + Add (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, neste exemplo, digite ["Hello", "World!"].

  11. Clique em Adicionar.

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

Clique em Botão executar agora para executar o fluxo de trabalho. Para acessar view detalhes da execução, clique em view execution (visualizar execução ) na janela pop-up Triggered execution (execução acionada ) ou clique no link na coluna começar time (tempo ) da execução no Job execution view.

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

Limites de tamanho de saída para JAR Job

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

Para evitar esse limite, o senhor pode impedir que o stdout seja retornado do driver para a Databricks definindo a configuração spark.databricks.driver.disableScalaOutput do Spark como true. Em default, o valor do sinalizador é false. O sinalizador controla a saída de células para Scala JAR Job e Scala Notebook. Se o sinalizador estiver ativado, o site Spark não retornará os resultados da execução do trabalho para o cliente. O sinalizador não afeta os dados que são gravados clusternos log arquivos do . Databricks recomenda definir esse sinalizador somente para o Job clusters para o JAR Job porque ele desativa os resultados do Notebook.

Recomendação: Use o SparkContextcompartilhado.

Como o Databricks é um serviço gerenciado, talvez sejam necessárias algumas alterações no código para garantir que o Apache Spark Job seja executado corretamente. JAR Os programas de trabalho devem usar o SparkContext compartilhado API para obter o SparkContext. Como o Databricks inicializa o SparkContext, os programas que invocam o new SparkContext() falharão. Para obter o SparkContext, use apenas o SparkContext compartilhado criado pela Databricks:

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

Há também vários métodos que o senhor 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 programa Main. Isso pode causar um comportamento indefinido.

Recomendação: Usar blocos try-finally para limpeza do trabalho

Considere um JAR que consiste em duas partes:

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

  • jobCleanup() que deve ser executada após jobBody(), independentemente de a função ter sido bem-sucedida ou ter retornado uma exceção.

Por exemplo, jobBody() cria tabelas e jobCleanup() elimina 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()
}

O senhor não deve tentar fazer a limpeza usando sys.addShutdownHook(jobCleanup) ou o código a seguir:

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

Devido à forma como a vida útil dos contêineres Spark é gerenciada em Databricks, os ganchos de desligamento não são executados de forma confiável.

Configuração dos parâmetros do trabalho JAR

O senhor 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 a operação Create a new Job (POST /jobs/create) em Jobs API. Para acessar esses parâmetros, inspecione a matriz String passada para a função main.

gerenciar dependências da biblioteca

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

Para obter a lista completa das dependências do driver da biblioteca, 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 o senhor deseja examinar):

%sh
ls /databricks/jars

Quando o senhor define as dependências de biblioteca para JARs, a Databricks recomenda listar o Spark e o Hadoop como dependências provided. No Maven, adicione o Spark e o 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 o Spark e o 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 correta do Scala para suas dependências com base na versão que está sendo executada.

Próximas etapas

Para saber mais sobre como criar e executar o Databricks Job, consulte Criar e executar Databricks Jobs.