Использование JAR-файла в задании Azure Databricks

Архив Java или [JAR](https://en.wikipedia.org/wiki/JAR_(file_format) формат файла основан на популярном формате ZIP-файла и используется для агрегирования множества файлов Java или Scala в один. С помощью задачи JAR можно обеспечить быструю и надежную установку кода Java или Scala в заданиях Azure Databricks. В этой статье приведен пример создания JAR-файла и задания, запускающего приложение, упаковаемое в JAR-файл. В этом примере вы будете:

  • Создайте проект JAR, определяющий пример приложения.
  • Упаковайте примеры файлов в JAR-файл.
  • Создайте задание для запуска JAR-файла.
  • Запустите задание и ознакомьтесь с результатами.

Перед началом работы

Для выполнения этого примера вам потребуется следующее:

  • Для java JARs пакет средств разработки Java (JDK).
  • Для Scala JARs, JDK и sbt.

Шаг 1. Создание локального каталога для примера

Создайте локальный каталог для хранения примера кода и созданных артефактов, например databricks_jar_test.

Шаг 2. Создание JAR-файла

Выполните следующие инструкции, чтобы создать JAR-файл с помощью Java или Scala.

Создание JAR-файла Java

  1. В папке databricks_jar_test создайте файл с именем PrintArgs.java со следующим содержимым:

    import java.util.Arrays;
    
    public class PrintArgs {
      public static void main(String[] args) {
        System.out.println(Arrays.toString(args));
      }
    }
    
  2. PrintArgs.java Скомпилируйте файл, создающий файлPrintArgs.class:

    javac PrintArgs.java
    
  3. (Необязательно) Запустите скомпилированную программу:

    java PrintArgs Hello World!
    
    # [Hello, World!]
    
  4. В той же папке, что PrintArgs.java и PrintArgs.class файлы, создайте папку с именем META-INF.

  5. В папке META-INF создайте файл с именем MANIFEST.MF со следующим содержимым. Обязательно добавьте новую строку в конце этого файла:

    Main-Class: PrintArgs
    
  6. В корне databricks_jar_test папки создайте JAR-файл с именем PrintArgs.jar:

    jar cvfm PrintArgs.jar META-INF/MANIFEST.MF *.class
    
  7. (Необязательно) Чтобы проверить его, запустите JAR-файл из корневого databricks_jar_test каталога:

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

    Примечание.

    Если вы получите ошибку no main manifest attribute, in PrintArgs.jar, обязательно добавьте новую строку в конец MANIFEST.MF файла, а затем попробуйте создать и запустить JAR-файл еще раз.

  8. Отправка PrintArgs.jar в том. См. раздел "Отправка файлов в том каталога Unity".

Создание JAR-файла Scala

  1. databricks_jar_test Создайте пустой файл build.sbt из папки со следующим содержимым:

    ThisBuild / scalaVersion := "2.12.14"
    ThisBuild / organization := "com.example"
    
    lazy val PrintArgs = (project in file("."))
      .settings(
        name := "PrintArgs"
      )
    
  2. databricks_jar_test Создайте структуру src/main/scala/exampleпапок из папки.

  3. В папке example создайте файл с именем PrintArgs.scala со следующим содержимым:

    package example
    
    object PrintArgs {
      def main(args: Array[String]): Unit = {
        println(args.mkString(", "))
      }
    }
    
  4. Скомпилируйте программу:

    sbt compile
    
  5. (Необязательно) Запустите скомпилированную программу:

    sbt "run Hello World\!"
    
    # Hello, World!
    
  6. В папке databricks_jar_test/project создайте файл с именем assembly.sbt со следующим содержимым:

    addSbtPlugin("com.eed3si9n" % "sbt-assembly" % "2.0.0")
    
  7. В корневой databricks_jar_test папке выполните assembly команду, которая создает JAR-файл в папке target :

    sbt assembly
    
  8. (Необязательно) Чтобы проверить его, запустите JAR-файл из корневого databricks_jar_test каталога:

    java -jar target/scala-2.12/PrintArgs-assembly-0.1.0-SNAPSHOT.jar Hello World!
    
    # Hello, World!
    
  9. Отправка PrintArgs-assembly-0.1.0-SNAPSHOT.jar в том. См. раздел "Отправка файлов в том каталога Unity".

Шаг 3. Создание задания Azure Databricks для запуска JAR-файла

  1. Перейдите на целевую страницу Azure Databricks и выполните одно из следующих действий:
    • На боковой панели щелкните "Рабочие процессы" и щелкните .Кнопка Значок рабочих процессов
    • На боковой панели нажмите кнопку Значок "Создать " и выберите "Задание " в меню.
  2. В диалоговом окне задачи, которое отображается на вкладке "Задачи ", замените имя задания... например JAR example.
  3. В поле "Имя задачи" введите имя задачи, например java_jar_task Java или scala_jar_task Scala.
  4. Для типа выберите JAR.
  5. Для основного класса в этом примере введите PrintArgs для Java или example.PrintArgs Scala.
  6. Для кластера выберите совместимый кластер. Ознакомьтесь с поддержкой библиотеки Java и Scala.
  7. Для зависимых библиотек нажмите кнопку +Добавить.
  8. В диалоговом окне "Добавление зависимой библиотеки" с выбранными томами введите расположение, в котором вы отправили JAR-файл (PrintArgs.jarилиPrintArgs-assembly-0.1.0-SNAPSHOT.jar) на предыдущем шаге в путь к файлу томов, или отфильтруйте или найдите JAR-файл. Выберите ее.
  9. Нажмите кнопку Добавить.
  10. Для параметров в этом примере введите ["Hello", "World!"].
  11. Нажмите кнопку Добавить.

Шаг 4. Запуск задания и просмотр сведений о выполнении задания

Щелкните Кнопка , чтобы запустить рабочий процесс. Чтобы просмотреть сведения о выполнении, нажмите кнопку "Вид" во всплывающем окне запуска или щелкните ссылку в столбце " Время начала" для запуска в представлении выполнения задания.

По завершении выполнения выходные данные отображаются на панели вывода , включая аргументы, переданные задаче.

Ограничения размера выходных данных для заданий JAR

Для выходных данных задания, таких как выходные данные журнала, передаваемые в stdout, применяется ограничение размера 20 МБ. Если общий объем выходных данных имеет больший размер, выполнение отменяется и помечается как завершенное с ошибкой.

Чтобы избежать этого ограничения, можно запретить возврат stdout из драйвера в Azure Databricks, присвоив параметру spark.databricks.driver.disableScalaOutput в конфигурации Spark значение true. По умолчанию флаг имеет значение false. Флаг контролирует выходные данные ячейки для заданий JAR Scala и записных книжек Scala. Если флаг включен, Spark не возвращает клиенту результаты выполнения задания. Флаг не влияет на данные, записываемые в файлы журналов кластера. Databricks рекомендует задать этот флаг только для кластеров заданий JAR, так как он отключает результаты записной книжки.

Рекомендация. Использование общего доступа SparkContext

Так как Azure Databricks — это управляемая служба, некоторые изменения кода могут потребоваться для правильного выполнения заданий Apache Spark. Программы заданий JAR должны использовать общий API SparkContext для получения SparkContext. Поскольку Azure Databricks инициализирует SparkContext, программы, которые вызывают ошибку new SparkContext(), завершаются с ошибкой. Для получения SparkContext используйте только общий SparkContext, созданный Azure Databricks:

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

Некоторых методов при использовании общего SparkContext следует избегать.

  • Не вызывайте SparkContext.stop().
  • Не вызывайте System.exit(0) или sc.stop() в конце программы Main. Это может привести к неопределенному поведению.

Рекомендация. Использование try-finally блоков для очистки задания

Возьмем для примера JAR, состоящий из двух частей:

  • jobBody() — содержит основную часть задания;
  • jobCleanup() который должен выполняться после jobBody()того, успешно ли эта функция выполнена или возвращена исключение.

Например, jobBody() создает таблицы и jobCleanup() удаляет эти таблицы.

Безопасный способ убедиться, что метод очистки вызывается, заключается в том, чтобы поместить try-finally блок в код:

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

Не пытайтесь использовать для очистки sys.addShutdownHook(jobCleanup) или следующий код:

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

Так как время существования контейнеров Spark управляется в Azure Databricks, перехватчики завершения работы не выполняются надежно.

Настройка параметров задания JAR

Передача параметров в задания JAR выполняется с помощью массива строк в формате JSON. См. объект spark_jar_task в тексте запроса, передаваемый в операцию Создать задачу (POST /jobs/create) в API заданий. Для доступа к этим параметрам проверьте массив String, переданный в функцию main.

Управление зависимостями библиотек

Драйвер Spark имеет определенные зависимости библиотек, которые не могут быть переопределены. Если задание добавляет конфликтующие библиотеки, зависимости библиотеки драйверов Spark имеют приоритет.

Чтобы получить полный список зависимостей библиотеки драйверов, выполните следующую команду в записной книжке, подключенной к кластеру, настроенной с той же версией Spark (или кластером с драйвером, который требуется проверить):

%sh
ls /databricks/jars

При определении зависимостей библиотеки для JAR Databricks рекомендует перечислять Spark и Hadoop в качестве provided зависимостей. В Maven добавьте Spark и Hadoop в качестве указанных зависимостей:

<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>

Добавьте sbtSpark и Hadoop в качестве указанных зависимостей:

libraryDependencies += "org.apache.spark" %% "spark-core" % "2.3.0" % "provided"
libraryDependencies += "org.apache.hadoop" %% "hadoop-core" % "1.2.1" % "provided"

Совет

Укажите правильную версию Scala для ваших зависимостей, исходя из используемой вами версии.

Дальнейшие действия

Дополнительные сведения о создании и запуске заданий Azure Databricks см. в статье "Планирование и оркестрация рабочих процессов".