在 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
在
databricks_jar_test
資料夾中,使用下列內容來建立名為PrintArgs.java
檔案:import java.util.Arrays; public class PrintArgs { public static void main(String[] args) { System.out.println(Arrays.toString(args)); } }
編譯檔案
PrintArgs.java
,這會建立 檔案PrintArgs.class
:javac PrintArgs.java
(選擇性) 執行編譯的程式:
java PrintArgs Hello World! # [Hello, World!]
在與
PrintArgs.java
和PrintArgs.class
檔案相同的資料夾中,建立名為META-INF
的資料夾。在
META-INF
資料夾中,使用下列內容來建立名為MANIFEST.MF
檔案。 請務必在此檔案結尾加入新行:Main-Class: PrintArgs
從
databricks_jar_test
資料夾的根目錄中,建立名為PrintArgs.jar
的 JAR:jar cvfm PrintArgs.jar META-INF/MANIFEST.MF *.class
(選擇性) 若要測試,請從資料夾的
databricks_jar_test
根目錄執行 JAR:java -jar PrintArgs.jar Hello World! # [Hello, World!]
注意
如果您收到錯誤
no main manifest attribute, in PrintArgs.jar
,請務必在MANIFEST.MF
檔案結尾加入新行,然後再嘗試建立並執行 JAR。上傳
PrintArgs.jar
至磁碟區。 請參閱將檔案上傳至 Unity Catalog 磁碟區。
建立 Scala JAR
在
databricks_jar_test
資料夾中,使用下列內容來建立名為build.sbt
的空白檔案:ThisBuild / scalaVersion := "2.12.14" ThisBuild / organization := "com.example" lazy val PrintArgs = (project in file(".")) .settings( name := "PrintArgs" )
從
databricks_jar_test
資料夾建立資料夾結構src/main/scala/example
。在
example
資料夾中,使用下列內容來建立名為PrintArgs.scala
檔案:package example object PrintArgs { def main(args: Array[String]): Unit = { println(args.mkString(", ")) } }
編譯該程式:
sbt compile
(選擇性) 執行編譯的程式:
sbt "run Hello World\!" # Hello, World!
在
databricks_jar_test/project
資料夾中,使用下列內容來建立名為assembly.sbt
檔案:addSbtPlugin("com.eed3si9n" % "sbt-assembly" % "2.0.0")
從
databricks_jar_test
資料夾的根目錄執行assembly
命令,這會在資料夾下target
產生 JAR:sbt assembly
(選擇性) 若要測試,請從資料夾的
databricks_jar_test
根目錄執行 JAR:java -jar target/scala-2.12/PrintArgs-assembly-0.1.0-SNAPSHOT.jar Hello World! # Hello, World!
上傳
PrintArgs-assembly-0.1.0-SNAPSHOT.jar
至磁碟區。 請參閱將檔案上傳至 Unity Catalog 磁碟區。
步驟 3. 建立 Azure Databricks 作業以執行 JAR
- 移至您的 Azure Databricks 登陸頁面,並執行下列其中一項:
- 按下側邊欄中的 [工作流程],然後按下 。
- 在側邊欄中,按下 [新增],然後從功能表中選取 [作業]。
- 在 [工作] 索引標籤上出現的 [工作] 對話方塊中,以您的作業名稱取代 [新增工作名稱...],例如
JAR example
。 - 針對 [工作名稱],輸入工作的名稱,例如 Java 的
java_jar_task
或 Scala 的scala_jar_task
。 - 在 [類型] 中,選取 [JAR]。
- 針對 [主類別],在此範例中,輸入 Java 的
PrintArgs
或 Scala 的example.PrintArgs
。 - 針對 [叢集],選取相容的叢集。 請參閱 Java 和 Scala 程式庫支援。
- 針對 [相依程式庫],按下 [+ 新增]。
- 在 [新增相依程式庫] 對話方塊中,選取 [磁碟區],輸入您在上一個步驟中將 JAR (
PrintArgs.jar
或PrintArgs-assembly-0.1.0-SNAPSHOT.jar
) 上傳至 [磁碟區檔案路徑]的位置,或篩選或瀏覽以尋找 JAR。 選取該連結。 - 按一下 [新增]。
- 針對 [參數],在此範例中,輸入
["Hello", "World!"]
。 - 按一下 [新增]。
步驟 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 作業,請參閱排程和協調工作流程。