共用方式為


在 Azure Databricks 作業中使用 JAR

Java 封存或 [JAR] (https://en.wikipedia.org/wiki/JAR_(file_format) 檔格式是以熱門的 ZIP 檔案格式為基礎,用來將許多 Java 或 Scala 檔案匯總成一個。 匯使用 JAR 工作,您可以確保 Azure Databricks 作業中 Java 或 Scala 程式碼的快速且可靠安裝。 本文提供建立 JAR 的範例,以及執行在 JAR 中封裝之應用程式的作業。 在此範例中,您將會:

  • 建立定義範例應用程式的 JAR 專案。
  • 將範例檔案統合成 JAR。
  • 建立執行 JAR 的作業。
  • 執行作業並檢視結果。

開始之前

若要完成此範例,您需要下列各項:

  • 針對 Java JAR,Java 開發工具套件 (JDK)。
  • 針對 Scala JAR,JDK 和 sbt。

步驟 1:建立範例的本機目錄

建立本機目錄以儲存範例程式碼和產生的成品,例如 databricks_jar_test

步驟 2:建立 JAR

完成下列指示,以使用Java或 Scala 來建立 JAR。

建立 Java JAR

  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.javaPrintArgs.class 檔案相同的資料夾中,建立名為 META-INF 的資料夾。

  5. META-INF 資料夾中,使用下列內容來建立名為 MANIFEST.MF 檔案。 請務必在此檔案結尾加入新行:

    Main-Class: PrintArgs
    
  6. databricks_jar_test 資料夾的根目錄中,建立名為 PrintArgs.jar 的 JAR:

    jar cvfm PrintArgs.jar META-INF/MANIFEST.MF *.class
    
  7. (選擇性) 若要測試,請從資料夾的 databricks_jar_test 根目錄執行 JAR:

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

    注意

    如果您收到錯誤 no main manifest attribute, in PrintArgs.jar,請務必在 MANIFEST.MF 檔案結尾加入新行,然後再嘗試建立並執行 JAR。

  8. 上傳 PrintArgs.jar 至磁碟區。 請參閱將檔案上傳至 Unity Catalog 磁碟區

建立 Scala JAR

  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 命令,這會在資料夾下 target 產生 JAR:

    sbt assembly
    
  8. (選擇性) 若要測試,請從資料夾的 databricks_jar_test 根目錄執行 JAR:

    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 Catalog 磁碟區

步驟 3. 建立 Azure Databricks 作業以執行 JAR

  1. 移至您的 Azure Databricks 登陸頁面,並執行下列其中一項:
    • 按下側邊欄中的 工作流程圖示 [工作流程],然後按下 [建立作業] 按鈕
    • 在側邊欄中,按下 新增圖示 [新增],然後從功能表中選取 [作業]
  2. 在 [工作] 索引標籤上出現的 [工作] 對話方塊中,以您的作業名稱取代 [新增工作名稱...],例如 JAR example
  3. 針對 [工作名稱],輸入工作的名稱,例如 Java 的 java_jar_task 或 Scala 的 scala_jar_task
  4. 在 [類型] 中,選取 [JAR]
  5. 針對 [主類別],在此範例中,輸入 Java 的 PrintArgs 或 Scala 的 example.PrintArgs
  6. 針對 [叢集],選取相容的叢集。 請參閱 Java 和 Scala 程式庫支援
  7. 針對 [相依程式庫],按下 [+ 新增]
  8. 在 [新增相依程式庫] 對話方塊中,選取 [磁碟區],輸入您在上一個步驟中將 JAR (PrintArgs.jarPrintArgs-assembly-0.1.0-SNAPSHOT.jar) 上傳至 [磁碟區檔案路徑]的位置,或篩選或瀏覽以尋找 JAR。 選取該連結。
  9. 按一下新增
  10. 針對 [參數],在此範例中,輸入 ["Hello", "World!"]
  11. 按一下新增

步驟 4:執行作業並檢視作業執行詳細資料

按下 [立即執行] 按鈕 以執行工作流程。 若要檢視 [執行的詳細資料],請按下 [觸發的執行] 快顯視窗中的 [檢視執行],或按下 [作業執行] 檢視中執行之 [開始時間] 資料行中的連結。

執行完成時,輸出會顯示在 [輸出] 面板中,包括傳遞至工作的引數。

JAR 作業的輸出大小限制

作業輸出,例如發出至 stdout 的記錄輸出,會受限於 20 MB 的大小限制。 如果總輸出的大小較大,將會取消執行,並標示為失敗。

若要避免遇到此限制,您可以將 spark.databricks.driver.disableScalaOutput Spark 組態設為 true,以防止從驅動程式傳回 Azure Databricks。 根據預設,此值為 false。 旗標可控制 Scala JAR 作業和 Scala 筆記本的儲存格輸出。 如果已啟用旗標,Spark 不會將作業執行結果傳回用戶端。 旗標不會影響在叢集記錄檔中寫入的資料。 Databricks 建議只針對 JAR 作業的作業叢集設定此旗標,因為那會停用筆記本結果。

建議:使用共用的 SparkContext

因為 Azure Databricks 是受管理的服務,因此可能需要一些程式碼變更,以確保 Apache Spark 作業能夠正確執行。 JAR 作業程式必須使用共用的 SparkContext API 來取得 SparkContext。 因為 Azure Databricks 會初始化 SparkContext,因此叫用 new SparkContext() 的程式將會失敗。 若要取得 SparkContext,請只使用 Azure Databricks 所建立的共用 SparkContext

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

使用共用的 SparkContext時,您也應該避免使用數種方法。

  • 不要呼叫 SparkContext.stop()
  • 請勿在 Main 應用程式結尾呼叫 System.exit(0)sc.stop()。 這可能會導致未定義的行為。

建議:使用 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 作業參數

您可以使用 JSON 字串陣列將參數傳遞至 JAR 作業。 請參閱傳遞至作業 API 中[建立新作業]操作 (POST /jobs/create) 之要求本文中的 spark_jar_task 物件。 若要存取這些參數,請檢查傳入 main 函式的 String 陣列。

套件組合程式庫相依性

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>

sbt 中,新增 Spark 和 Hadoop 做為提供的相依性:

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

提示

根據您執行的版本,為您的相依性指定正確的 Scala 版本。

後續步驟

若要深入瞭解如何建立和執行 Azure Databricks 作業,請參閱排程和協調工作流程