Usare Azure Toolkit for IntelliJ per eseguire il debug remoto di applicazioni Apache Spark in HDInsight tramite VPN

È consigliabile usare la modalità di debug dell'applicazione Apache Spark da remoto tramite SSH. Per istruzioni vedere Eseguire il debug remoto delle applicazioni Apache Spark su un cluster HDInsight con Azure Toolkit per IntelliJ tramite SSH.

Questo articolo offre indicazioni dettagliate su come usare gli strumenti HDInsight in Azure Toolkit for IntelliJ per inviare un processo Spark nel cluster HDInsight Spark e quindi eseguirne il debug remoto dal computer desktop. Per completare queste attività, è necessario seguire la procedura di alto livello seguente:

  1. Creare una rete virtuale di Azure da sito a sito o da punto a sito. Le procedure descritte in questo documento presuppongono che si usi una rete da sito a sito.
  2. Creare un cluster Spark in HDInsight incluso nella rete virtuale da sito a sito.
  3. Verificare la connettività tra il nodo head del cluster e il PC desktop.
  4. Creare un'applicazione Scala in IntelliJ IDEA e configurarla per il debug remoto.
  5. Eseguire l'applicazione ed effettuarne il debug.

Prerequisiti

Passaggio 1: Creare una rete virtuale di Azure

Seguire le istruzioni riportate nei collegamenti seguenti per creare una rete virtuale di Azure e quindi verificare la connettività tra il PC desktop e la rete virtuale:

Passaggio 2: Creare un cluster HDInsight Spark

È consigliabile creare anche un cluster Apache Spark in Azure HDInsight incluso nella rete virtuale di Azure creata. Usare le informazioni disponibili in Creare cluster basati su Linux in HDInsight. Nell'ambito della configurazione facoltativa, selezionare la rete virtuale di Azure creata nel passaggio precedente.

Passaggio 3: Verificare la connettività tra il nodo head del cluster e il PC desktop

  1. Ottenere l'indirizzo IP del nodo head. Aprire l'interfaccia utente di Ambari per il cluster. Dal pannello del cluster selezionare Dashboard.

    Select Dashboard in Apache Ambari.

  2. Nell'interfaccia utente di Ambari selezionare Hosts (Host).

    Select Hosts in Apache Ambari.

  3. Viene visualizzato un elenco di nodi head, nodi del ruolo di lavoro e nodi zookeeper. I nodi head hanno un prefisso hn\*. Selezionare il primo nodo head.

    Find the head node in Apache Ambari.

  4. Nella parte inferiore della pagina visualizzata, nel riquadro Summary (Riepilogo) copiare l'indirizzo IP del nodo head e il nome host.

    Find the IP address in Apache Ambari.

  5. Aggiungere l'indirizzo IP e il nome host del nodo head nel file host nel computer in cui si vuole eseguire il processo Spark ed effettuarne il debug remoto. Sarà così possibile comunicare con il nodo head usando sia l'indirizzo IP che il nome host.

    a. Aprire un file del Blocco note con autorizzazioni elevate. Scegliere Apri dal menu File e quindi passare al percorso del file host. In un computer Windows il percorso è C:\Windows\System32\Driver\etc\host.

    b. Aggiungere al file host le informazioni seguenti:

    # 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. Nel computer che è stato connesso alla rete virtuale di Azure usata dal cluster HDInsight verificare che sia possibile effettuare il ping dei nodi head usando sia l'indirizzo IP che il nome host.

  7. Usare SSH per connettersi al nodo head del cluster seguendo le istruzioni riportate in Connettersi a un cluster HDInsight con SSH. Dal nodo head del cluster effettuare il ping dell'indirizzo IP del computer desktop. Testare la connettività per entrambi gli indirizzi IP assegnati al computer:

    • uno per la connessione di rete
    • uno per la rete virtuale di Azure
  8. Ripetere questi passaggi anche per l'altro nodo head.

Passaggio 4: Creare un'applicazione Apache Spark Scala usando gli strumenti HDInsight in Azure Toolkit for IntelliJ e configurarla per eseguire il debug remoto

  1. Aprire IntelliJ IDEA e creare un nuovo progetto. Nella finestra di dialogo New Project (Nuovo progetto) seguire questa procedura:

    Select the new project template in IntelliJ IDEA.

    a. Selezionare HDInsight>Spark on HDInsight (Scala) (Spark in HDInsight - Scala).

    b. Selezionare Avanti.

  2. Nella finestra di dialogo New Project (Nuovo progetto) successiva seguire questa procedura e quindi selezionare Finish (Fine):

    • Immettere il nome e la posizione di un progetto.

    • Nell'elenco a discesa Project SDK (SDK progetto) selezionare Java 1.8 per il cluster Spark 2.x o Java 1.7 per il cluster Spark 1.x.

    • Nell'elenco a discesa Spark version (Versione di Spark) la creazione guidata del progetto Scala inserisce la versione corretta per Spark SDK e Scala SDK. Se la versione del cluster Spark è precedente alla 2.0, selezionare Spark 1.x. In caso contrario, selezionare Spark2.x. Questo esempio usa Spark 2.0.2 (Scala 2.11.8).

    Select the project SDK and Spark version.

  3. Il progetto Spark crea automaticamente un artefatto. Per visualizzare l'elemento, seguire questa procedura:

    a. Dal menu File selezionare Project Structure (Struttura progetto).

    b. Nella finestra di dialogo Project Structure (Struttura progetto) selezionare Artifacts (Artefatti) per visualizzare l'artefatto predefinito creato. È anche possibile creare un artefatto personalizzato selezionando il segno più (+).

    IntelliJ IDEA artifacts create jar.

  4. Aggiungere librerie al progetto. Per aggiungere una raccolta, eseguire le operazioni seguenti:

    a. Fare clic con il pulsante destro del mouse sul nome del progetto nell'albero del progetto e quindi scegliere Open Module Settings(Apri impostazioni modulo).

    b. Nella finestra di dialogo Project Structure (Struttura progetto) selezionare Libraries (Librerie), scegliere il simbolo (+) e quindi From Maven (Da Maven).

    IntelliJ IDEA download library.

    c. Nella finestra di dialogo Download Library from Maven Repository (Scarica libreria da repository Maven) cercare e aggiungere le librerie seguenti:

    • org.scalatest:scalatest_2.10:2.2.1
    • org.apache.hadoop:hadoop-azure:2.7.1
  5. Copiare yarn-site.xml e core-site.xml dal nodo head del cluster e aggiungerli al progetto. Per copiare i file, usare i comandi riportati di seguito. Per copiare i file dai nodi head del cluster è possibile usare Cygwin per eseguire i comandi scp seguenti:

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

    Poiché gli indirizzi IP e i nomi host dei nodi head del cluster sono già stati aggiunti al file host nel PC desktop, si possono usare i comandi scp nel modo seguente:

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

    Aggiungere questi file al progetto copiandoli nella cartella /src dell'albero del progetto, ad esempio <your project directory>\src.

  6. Aggiornare il file core-site.xml per apportare le modifiche seguenti:

    a. Sostituire la chiave crittografata. Il file core-site.xml include la chiave crittografata per l'account di archiviazione associato al cluster. Nel file core-site.xml aggiunto al progetto sostituire la chiave crittografata con la chiave di archiviazione effettiva associata all'account di archiviazione predefinito. Per altre informazioni, vedere Gestire le chiavi di accesso dell'account di archiviazione.

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

    b. Rimuovere le voci seguenti da 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. Salvare il file.

  7. Aggiungere la classe principale per l'applicazione. In Project Explorer (Esplora progetti) fare clic con il pulsante destro del mouse su src, puntare a New (Nuovo) e quindi selezionare Scala class (Classe Scala).

    IntelliJ IDEA Select the main class.

  8. Nella finestra di dialogo Create New Scala Class (Crea nuova classe Scala) immettere un nome, selezionare Object (Oggetto) per il campo Kind (Tipologia) e quindi selezionare OK.

    IntelliJ IDEA Create new Scala class.

  9. Incollare il codice seguente nel file MyClusterAppMain.scala . Questo codice crea il contesto Spark e apre un metodo executeJob dall'oggetto 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. Ripetere i passaggi 8 e 9 per aggiungere un nuovo oggetto Scala denominato *SparkSample. Aggiungi il codice seguente a questa classe. Questo codice legge i dati da HVAC.csv disponibile in tutti i cluster HDInsight Spark. Recupera le righe con una sola cifra nella settima colonna del file CSV e scrive l'output in /HVACOut nel contenitore di archiviazione predefinito per il cluster.

    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. Ripetere i passaggi 8 e 9 per aggiungere una nuova classe denominata RemoteClusterDebugging. Questa classe implementa il framework di test Spark usato per il debug delle applicazioni. Aggiungere il codice seguente alla classe 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")
         }
        }
    

    Alcuni aspetti importanti da notare:

    • Per .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"), verificare che il file JAR dell'assembly Spark sia disponibile nell'archiviazione cluster al percorso specificato.
    • Per setJars, specificare il percorso in cui verrà creato il file JAR dell'elemento. In genere è <Your IntelliJ project directory>\out\<project name>_DefaultArtifact\default_artifact.jar.
  12. Nella classe *RemoteClusterDebugging fare clic con il pulsante destro del mouse sulla parola chiave test e scegliere Create RemoteClusterDebugging Configuration (Crea configurazione RemoteClusterDebugging).

    IntelliJ IDEA Create a remote configuration.

  13. Nella finestra di dialogo Create RemoteClusterDebugging Configuration (Crea configurazione RemoteClusterDebugging), specificare un nome per la configurazione e quindi selezionare Test kind (Tipo di test) come nome del test. Lasciare tutte le altre impostazioni predefinite. Selezionare Apply (Applica) e quindi OK.

    Create RemoteClusterDebugging Configuration.

  14. Nella barra dei menu verrà ora visualizzato un elenco a discesa della configurazione Remote Run (Esecuzione remota).

    IntelliJ The Remote run drop-down list.

Passaggio 5: Eseguire l'applicazione in modalità di debug

  1. Nel progetto IntelliJ IDEA aprire SparkSample.scala e creare un punto di interruzione accanto a val rdd1. Nel menu a comparsa Create Breakpoint for (Crea punto di interruzione) selezionare line in function executeJob (riga in funzione executeJob).

    IntelliJ IDEA Add a breakpoint.

  2. Per eseguire l'applicazione selezionare il pulsante Debug Run (Esecuzione debug) accanto all'elenco a discesa della configurazione Remote Run (Esecuzione remota).

    IntelliJ IDEA Select the Debug Run button.

  3. Quando l'esecuzione del programma raggiunge il punto di interruzione, nel riquadro inferiore verrà visualizzata una scheda Debugger.

    IntelliJ IDEA View the Debugger tab.

  4. Per aggiungere un'espressione di controllo, selezionare l'icona (+).

    IntelliJ debug-add-watch-variable.

    In questo esempio, l'applicazione si è interrotta prima che la variabile rdd1 fosse creata. Tramite questa espressione di controllo, possiamo vedere le prime cinque righe nella variabile rdd. Selezionare INVIO.

    IntelliJ Run the program in debug mode.

    L'immagine precedente mostra che in fase di esecuzione è possibile eseguire query su terabyte di dati e il debug dell'avanzamento dell'applicazione. Nell'output illustrato nell'immagine precedente, ad esempio, si può osservare che la prima riga dell'output è un'intestazione. Sulla base di questo output, è possibile modificare il codice dell'applicazione per ignorare la riga di intestazione, se necessario.

  5. È ora possibile fare clic sull'icona Resume Program (Riprendi programma) per continuare l'esecuzione dell'applicazione.

    IntelliJ IDEA Select Resume Program.

  6. Se l'applicazione viene completata correttamente, verrà visualizzato un output simile al seguente:

    IntelliJ IDEA debugger console output.

Passaggi successivi

Scenari

Creare ed eseguire applicazioni

Strumenti ed estensioni

Gestione risorse