使用適用於 IntelliJ 的 Azure 工具組,透過 VPN 從遠端對 HDInsight 中的 Apache Spark 應用程式進行偵錯

建議您透過 SSH 從遠端對 Apache Spark 應用程式進行偵錯。 如需指示,請參閱 使用 Azure Toolkit for IntelliJ 透過 SSH 從遠端偵錯 HDInsight 叢集上的 Apache Spark 應用程式。

本文提供如何使用 Azure Toolkit for IntelliJ 中的 HDInsight 工具,在 HDInsight Spark 叢集上提交 Spark 作業的逐步指引,然後從桌面電腦從遠端偵錯它。 若要完成這些工作,您必須執行下列高階步驟:

  1. 建立站對站或點對站 Azure 虛擬網路。 本檔中的步驟假設您使用站對站網路。
  2. 在 HDInsight 中建立屬於站對站虛擬網路一部分的 Spark 叢集。
  3. 確認叢集前端節點與桌面之間的連線。
  4. 在 IntelliJ IDEA 中建立 Scala 應用程式,然後將其設定為遠端偵錯。
  5. 執行並偵錯應用程式。

必要條件

  • Azure 訂用帳戶。 如需詳細資訊,請參閱 取得 Azure 的免費試用版。
  • HDInsight 中的 Apache Spark 叢集。 如需指示,請參閱在 Azure HDInsight 中建立 Apache Spark 叢集
  • Oracle Java 開發工具包。 您可以從 Oracle 網站安裝它
  • IntelliJ IDEA。 本文使用 2017.1 版。 您可以從 JetBrains 網站 \(英文\) 安裝它。
  • 適用於 IntelliJ 的 Azure 工具組中的 HDInsight 工具。 適用於 IntelliJ 的 HDInsight 工具是適用於 IntelliJ 的 Azure 工具組的一部分。 如需如何安裝 Azure 工具組的指示,請參閱 安裝適用於 IntelliJ 的 Azure 工具組。
  • 從 IntelliJ IDEA 登入您的 Azure 訂用帳戶。 請遵循使用適用於 IntelliJ 的 Azure 工具組來建立 HDInsight 叢集的 Apache Spark 應用程式中的指示。
  • 例外狀況因應措施。 在 Windows 電腦上執行 Spark Scala 應用程式進行遠端偵錯時,您可能會收到例外狀況。 SPARK-2356說明此例外狀況,並因為 Windows 中遺漏WinUtils.exe檔案而發生。 若要解決此問題,您必須將Winutils.exe下載至 C:\WinUtils\bin 之類的位置。 新增HADOOP_HOME環境變數,然後將變數的值設定為 C\WinUtils

步驟 1:建立 Azure 虛擬網路

請遵循下列連結中的指示來建立 Azure 虛擬網路,然後確認桌面電腦與虛擬網路之間的連線:

步驟 2:建立 HDInsight Spark 叢集

建議您也在 Azure HDInsight 中建立 Apache Spark 叢集,該叢集是您所建立 Azure 虛擬網路的一部分。 使用在 HDInsight 中建立以 Linux 為基礎的叢集中可用的資訊。 在選擇性設定中,選取您在上一個步驟中建立的 Azure 虛擬網路。

步驟 3:確認叢集前端節點與桌面之間的連線能力

  1. 取得前端節點的IP位址。 開啟叢集的Ambari UI。 從 [叢集] 刀鋒視窗中,選取 [ 儀錶板]。

    Select Dashboard in Apache Ambari.

  2. 從Ambari UI中,選取 [ 主機]。

    Select Hosts in Apache Ambari.

  3. 您會看到前端節點、背景工作節點和 Zookeeper 節點的清單。 前端節點具有 hn* 前置詞。 選取第一個前端節點。

    Find the head node in Apache Ambari.

  4. 從頁面底部的 [摘要] 窗格中,複製前端節點的IP位址主機名

    Find the IP address in Apache Ambari.

  5. 將前端節點的IP位址和主機名新增至 您要執行並遠端偵錯 Spark 作業之電腦上的主機 檔案。 這可讓您使用IP位址和主機名來與前端節點通訊。

    a. 使用提高的許可權開啟 記事本 檔案。 從 [ 檔案] 功能表中,選取 [ 開啟],然後尋找主機檔案的位置。 在 Windows 計算機上,位置為 C:\Windows\System32\Drivers\etc\hosts

    b. 將下列資訊新增至 主機 檔案:

    # For headnode0
    192.xxx.xx.xx nitinp
    192.xxx.xx.xx nitinp.lhwwghjkpqejawpqbwcdyp3.gx.internal.cloudapp.net
    
    # For headnode1
    192.xxx.xx.xx nitinp
    192.xxx.xx.xx nitinp.lhwwghjkpqejawpqbwcdyp3.gx.internal.cloudapp.net
    
  6. 從您連線到 HDInsight 叢集所使用之 Azure 虛擬網路的電腦,確認您可以使用 IP 位址以及主機名來 Ping 前端節點。

  7. 依照使用 SSH 連線 HDInsight 叢集中的指示,使用 SSH 連線到叢集前端節點。 從叢集前端節點,偵測桌面電腦的IP位址。 測試指派給計算機的兩個IP位址的連線能力:

    • 一個用於網路連線
    • Azure 虛擬網路的其中一個
  8. 重複其他前端節點的步驟。

步驟 4:在 Azure Toolkit for IntelliJ 中使用 HDInsight Tools 建立 Apache Spark Scala 應用程式,並將其設定為遠端偵錯

  1. 開啟 IntelliJ IDEA 並建立新的專案。 在 [ 新增專案 ] 對話框中,執行下列動作:

    Select the new project template in IntelliJ IDEA.

    a. 在 HDInsight 上選取 [HDInsight>Spark] [Scala]。

    b. 選取 [下一步]。

  2. 在下一個 [新增專案 ] 對話框中,執行下列動作,然後選取 [ 完成]:

    • 輸入專案名稱和位置。

    • 在 [Project SDK] \(專案 SDK\) 下拉式清單中,針對 Spark 2.x 叢集,請選取 [Java 1.8] ,針對 Spark 1.x 叢集,則選取 [Java 1.7] 。

    • Spark版本 下拉式清單中,Scala 專案建立精靈會整合Spark SDK和 Scala SDK 的適當版本。 如果 Spark 叢集版本早於 2.0,請選取 [Spark 1.x] 。 否則,請選取 [Spark 2.x] 。 此範例使用 [Spark 2.0.2 (Scala 2.11.8)] 。

    Select the project SDK and Spark version.

  3. Spark 專案會自動為您建立成品。 若要檢視成品,請執行下列動作:

    a. 從 [ 檔案] 功能表中,選取 [項目結構]。

    b. 在 [Project Structure] \(專案結構\) 對話方塊中,選取 [Artifacts] \(成品\) 以檢視所建立的預設成品。 您也可以選取加號 ( + ) 來建立自己的成品。

    IntelliJ IDEA artifacts create jar.

  4. 將連結庫新增至您的專案。 若要新增連結庫,請執行下列動作:

    a. 以滑鼠右鍵按兩下專案樹狀結構中的專案名稱,然後選取 [開啟模組] 設定

    b. 在 [項目結構] 對話框中,選取 [連結庫],選取 (+) 符號,然後選取 [從 Maven]。

    IntelliJ IDEA download library.

    c. 在 [ 從 Maven 存放庫 下載連結庫] 對話框中,搜尋並新增下列連結庫:

    • org.scalatest:scalatest_2.10:2.2.1
    • org.apache.hadoop:hadoop-azure:2.7.1
  5. 從叢集前端節點複製 yarn-site.xmlcore-site.xml ,並將其新增至專案。 使用下列命令來複製檔案。 您可以使用 Cygwin 來執行下列 scp 命令,從叢集前端節點複製檔案:

    scp <ssh user name>@<headnode IP address or host name>://etc/hadoop/conf/core-site.xml .
    

    由於我們已在桌面上新增主機檔案的叢集前端節點 IP 位址和主機名,因此我們可以以下列方式使用 scp 命令:

    scp sshuser@nitinp:/etc/hadoop/conf/core-site.xml .
    scp sshuser@nitinp:/etc/hadoop/conf/yarn-site.xml .
    

    若要將這些檔案新增至您的專案,請在專案樹狀結構中的 /src 資料夾下複製它們,例如 <your project directory>\src

  6. core-site.xml更新檔案以進行下列變更:

    a. 取代加密金鑰。 檔案 core-site.xml 包含與叢集相關聯之記憶體帳戶的加密金鑰。 在您 core-site.xml 新增至項目的檔案中,將加密密鑰取代為與預設記憶體帳戶相關聯的實際記憶體密鑰。 如需詳細資訊,請參閱管理儲存體帳戶存取金鑰

    <property>
            <name>fs.azure.account.key.hdistoragecentral.blob.core.windows.net</name>
            <value>access-key-associated-with-the-account</value>
    </property>
    

    b. 從 core-site.xml移除下列項目:

    <property>
            <name>fs.azure.account.keyprovider.hdistoragecentral.blob.core.windows.net</name>
            <value>org.apache.hadoop.fs.azure.ShellDecryptionKeyProvider</value>
    </property>
    
    <property>
            <name>fs.azure.shellkeyprovider.script</name>
            <value>/usr/lib/python2.7/dist-packages/hdinsight_common/decrypt.sh</value>
    </property>
    
    <property>
            <name>net.topology.script.file.name</name>
            <value>/etc/hadoop/conf/topology_script.py</value>
    </property>
    

    c. 儲存檔案。

  7. 新增應用程式的主要類別。 從 [專案總管] 中,以滑鼠右鍵按兩下 src,指向 [新增],然後選取 [Scala 類別]。

    IntelliJ IDEA Select the main class.

  8. 在 [建立新的 Scala 類別] 對話框中,提供名稱、在 [種類] 方塊中選取 [物件],然後選取 [確定]。

    IntelliJ IDEA Create new Scala class.

  9. 在檔案中 MyClusterAppMain.scala ,貼上下列程序代碼。 此程式代碼會建立Spark內容,並從對象開啟 executeJob 方法 SparkSample

    import org.apache.spark.{SparkConf, SparkContext}
    
    object SparkSampleMain {
        def main (arg: Array[String]): Unit = {
        val conf = new SparkConf().setAppName("SparkSample")
                                    .set("spark.hadoop.validateOutputSpecs", "false")
        val sc = new SparkContext(conf)
    
        SparkSample.executeJob(sc,
                            "wasb:///HdiSamples/HdiSamples/SensorSampleData/hvac/HVAC.csv",
                            "wasb:///HVACOut")
        }
    }
    
  10. 重複步驟 8 和 9,以新增名為 *SparkSample的新 Scala 物件。 將下列代碼新增至此類別。 此程式代碼會從HVAC.csv讀取數據(適用於所有 HDInsight Spark 叢集)。 它會擷取 CSV 檔案中第七個數據行中只有一位數的數據列,然後將輸出 寫入叢集預設記憶體容器底下的 /HVACOut

    import org.apache.spark.SparkContext
    
    object SparkSample {
        def executeJob (sc: SparkContext, input: String, output: String): Unit = {
        val rdd = sc.textFile(input)
    
        //find the rows which have only one digit in the 7th column in the CSV
        val rdd1 =  rdd.filter(s => s.split(",")(6).length() == 1)
    
        val s = sc.parallelize(rdd.take(5)).cartesian(rdd).count()
        println(s)
    
        rdd1.saveAsTextFile(output)
        //rdd1.collect().foreach(println)
         }
    }
    
  11. 重複步驟 8 和 9,以新增名為 RemoteClusterDebugging的新類別。 這個類別會實作用來偵錯應用程式的Spark測試架構。 將下列程式碼新增至 RemoteClusterDebugging 類別:

        import org.apache.spark.{SparkConf, SparkContext}
        import org.scalatest.FunSuite
    
        class RemoteClusterDebugging extends FunSuite {
    
         test("Remote run") {
           val conf = new SparkConf().setAppName("SparkSample")
                                     .setMaster("yarn-client")
                                     .set("spark.yarn.am.extraJavaOptions", "-Dhdp.version=2.4")
                                     .set("spark.yarn.jar", "wasb:///hdp/apps/2.4.2.0-258/spark-assembly-1.6.1.2.4.2.0-258-hadoop2.7.1.2.4.2.0-258.jar")
                                     .setJars(Seq("""C:\workspace\IdeaProjects\MyClusterApp\out\artifacts\MyClusterApp_DefaultArtifact\default_artifact.jar"""))
                                     .set("spark.hadoop.validateOutputSpecs", "false")
           val sc = new SparkContext(conf)
    
           SparkSample.executeJob(sc,
             "wasb:///HdiSamples/HdiSamples/SensorSampleData/hvac/HVAC.csv",
             "wasb:///HVACOut")
         }
        }
    

    有幾個重要事項需要注意:

    • 針對 .set("spark.yarn.jar", "wasb:///hdp/apps/2.4.2.0-258/spark-assembly-1.6.1.2.4.2.0-258-hadoop2.7.1.2.4.2.0-258.jar"),請確定 Spark 元件 JAR 可在指定路徑的叢集記憶體上使用。
    • 針對 setJars,指定建立成品 JAR 的位置。 一般而言,它是 <Your IntelliJ project directory>\out\<project name>_DefaultArtifact\default_artifact.jar
  12. 在 類別中*RemoteClusterDebuggingtest,以滑鼠右鍵按兩下 關鍵詞,然後選取 [建立 RemoteClusterDebugging 組態]。

    IntelliJ IDEA Create a remote configuration.

  13. 在 [ 建立 RemoteClusterDebugging 組態 ] 對話框中,提供組態的名稱,然後選取 [測試種類 ] 作為 [測試名稱]。 將所有其他值保留為預設設定。 選取套用,然後選取確定

    Create RemoteClusterDebugging Configuration.

  14. 您現在應該會在選單列中看到 [遠端執行 組態] 下拉式清單。

    IntelliJ The Remote run drop-down list.

步驟 5:以偵錯模式執行應用程式

  1. 在您的 IntelliJ IDEA 專案中,開啟 SparkSample.scala 並建立旁 val rdd1的斷點。 在 [建立彈出視窗的 斷點] 功能表中,選取 函式 executeJob 中的行。

    IntelliJ IDEA Add a breakpoint.

  2. 若要執行應用程式,請選取 [遠端執行組態] 下拉式清單旁邊的 [偵錯執行] 按鈕。

    IntelliJ IDEA Select the Debug Run button.

  3. 當程式執行到達斷點時,您會在底部窗格中看到 [調試程式 ] 索引標籤。

    IntelliJ IDEA View the Debugger tab.

  4. 若要新增監看式,請選取 (+) 圖示。

    IntelliJ debug-add-watch-variable.

    在此範例中,應用程式會在建立變數 rdd1 之前中斷。 藉由使用此監看式,我們可以看到變數 中的前五個數據 rdd列。 選取 [輸入]

    IntelliJ Run the program in debug mode.

    您在上一個映射中看到的內容是,在運行時間,您可以查詢數 TB 的數據,並偵錯應用程式進度。 例如,在上一個影像中顯示的輸出中,您可以看到輸出的第一個數據列是標頭。 根據此輸出,您可以視需要修改應用程式程式代碼來略過標頭數據列。

  5. 您現在可以選取 [繼續程式 ] 圖示,以繼續執行應用程式。

    IntelliJ IDEA Select Resume Program.

  6. 如果應用程式順利完成,您應該會看到如下的輸出:

    IntelliJ IDEA debugger console output.

下一步

案例

建立及執行應用程式

工具和延伸模組

管理資源