分享方式:


在 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.class 檔案相同的資料夾中PrintArgs.java,建立名為 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. 建立 Azure Databricks 作業以執行 JAR

  1. 移至您的 Azure Databricks 登陸頁面,並執行下列其中一項:
    • 在提要欄位中,按兩下 工作流程圖示[工作流程],然後按下 。 建立作業按鈕
    • 在提要欄位中,按兩下 新增圖示 [新增 ],然後從功能表中選取 [作業 ]。
  2. 在 [工作] 索引標籤上出現的 [工作] 對話框中,以您的作業名稱取代 [新增工作名稱...],例如 JAR example
  3. 針對 [ 工作名稱],輸入工作的名稱,例如 java_jar_task Java 或 scala_jar_task Scala。
  4. 針對 [ 類型],選取 [JAR]。
  5. 針對Main類別,在此範例中,輸入 PrintArgs Java或 example.PrintArgs Scala。
  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 的大小限制。 如果總輸出的大小較大,則會取消執行並標示為失敗。

若要避免遇到此限制,您可以將Sparktrue組態設為 spark.databricks.driver.disableScalaOutput ,以防止從驅動程式傳回 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()
  • 請勿在應用程式結尾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 作業。 spark_jar_task請參閱傳遞至作業 API 中建立新作業作業 (POST /jobs/create) 的要求本文中的 物件。 若要存取這些參數,請檢查傳入函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 作業,請參閱 建立和執行 Azure Databricks 作業