共用方式為


在 Lakeflow 作業中使用 JAR

Java 封存或 JAR 檔案格式是以熱門的 ZIP 檔格式為基礎,並用來將許多 Java 或 Scala 檔案匯總成一個。 使用 JAR 工作,您可以在 Lakeflow 作業中確保 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 目錄磁碟區

建立 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 目錄磁碟區

步驟 3. 建立任務以執行 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,防止 stdout 從驅動程式傳回至 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()
  • 請勿在 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 作業參數

您使用 JSON 字串陣列將參數傳遞至 JAR 任務。 請參閱作業 API 中的「建立新作業」操作之要求本文中的 spark_jar_task 物件 ()。 若要存取這些參數,請檢查傳遞至 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>

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

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

提示

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

後續步驟

若要深入瞭解如何建立和執行作業,請參閱 Lakeflow 作業