Apache Spark: “impossible de lancer org.apache.spark.deploy.worker.Worker” ou Master

J’ai créé un cluster Spark sur Openstack fonctionnant sur Ubuntu14.04 avec 8 Go de RAM. J’ai créé deux machines virtuelles de 3 Go chacune (2 Go pour le système d’exploitation parent). De plus, je crée un maître et 2 travailleurs de la première machine virtuelle et 3 travailleurs de la seconde machine.

Le fichier spark-env.sh a un paramètre de base avec

export SPARK_MASTER_IP=10.0.0.30 export SPARK_WORKER_INSTANCES=2 export SPARK_WORKER_MEMORY=1g export SPARK_WORKER_CORES=1 

Chaque fois que je déploie le cluster avec start-all.sh, j’ai “échoué à lancer org.apache.spark.deploy.worker.Worker” et quelques fois “impossible de lancer org.apache.spark.deploy.master.Master”. Lorsque je vois le fichier journal pour rechercher une erreur, j’obtiens les informations suivantes:

Commande Spark: / usr / lib / jvm / java-7-openjdk-amd64 / bin / java -cp> /home/ubuntu/spark-1.5.1/sbin /../ conf /: / home / ubuntu / spark- > 1.5.1 / assembly / target / scala-2.10 / spark-assembly-1.5.1-> hadoop2.2.0.jar: /home/ubuntu/spark-1.5.1/lib_managed/jars/datanucleus-api-> jdo- 3.2.6.jar: /home/ubuntu/spark-1.5.1/lib_managed/jars/datanucleus-core-> 3.2.10.jar: /home/ubuntu/spark-1.5.1/lib_managed/jars/datanucleus-rdbms -> 3.2.9.jar -Xms1g -Xmx1g -XX: MaxPermSize = 256m> org.apache.spark.deploy.master.Master –ip 10.0.0.30 –port 7077 –webui-> port 8080

Bien que j’obtienne le message d’échec, mais le maître ou le travailleur devient vivant après quelques secondes.

Quelqu’un peut-il s’il vous plaît expliquer la raison?

Le système de configuration Spark est un gâchis de variables d’environnement, d’indicateurs d’argument et de fichiers de propriétés Java. Je viens de passer quelques heures à retrouver le même avertissement et à démêler la procédure d’initialisation Spark, et voici ce que j’ai trouvé:

  1. sbin/start-all.sh appelle sbin/start-master.sh (puis sbin/start-slaves.sh )
  2. sbin/start-master.sh appelle sbin/spark-daemon.sh start org.apache.spark.deploy.master.Master ...
  3. sbin/spark-daemon.sh start ... interrompt un appel à bin/spark-class org.apache.spark.deploy.master.Master ... , capture l’ID de processus résultant (pid), dort pendant 2 secondes, et vérifie ensuite si le nom de la commande de ce pid est “java”
  4. bin/spark-class est un script bash, il commence donc par le nom de la commande “bash” et procède à:
    1. (re) charger l’environnement Spark en sélectionnant bin/load-spark-env.sh
    2. trouve l’exécutable java
    3. trouve le bon pot Spark
    4. appelle java ... org.apache.spark.launcher.Main ... pour obtenir le classpath complet nécessaire à un déploiement Spark
    5. puis enfin, le contrôle, via exec , à java ... org.apache.spark.deploy.master.Master , où le nom de la commande devient “java”

Si les étapes 4.1 à 4.5 prennent plus de 2 secondes, ce qui dans mon (et votre) expérience semble inévitable sur un nouveau système d’exploitation où java n’a jamais été exécuté auparavant, vous obtenez le message “échec au lancement” avoir échoué.

Les esclaves se plaindront pour la même raison et se débattront jusqu’à ce que le maître soit réellement disponible, mais ils devraient continuer à réessayer jusqu’à ce qu’ils se connectent avec succès au maître.

J’ai un déploiement Spark assez standard sous EC2. J’utilise:

  • conf/spark-defaults.conf pour définir spark.executor.memory et append des jars personnalisés via spark.{driver,executor}.extraClassPath
  • conf/spark-env.sh pour définir SPARK_WORKER_CORES=$(($(nproc) * 2))
  • conf/slaves pour lister mes esclaves

Voici comment je lance un déploiement Spark, en contournant une partie du champ de mines / labyrinthe {bin,sbin}/*.sh :

 # on master, with SPARK_HOME and conf/slaves set appropriately mapfile -t ARGS < <(java -cp $SPARK_HOME/lib/spark-assembly-1.6.1-hadoop2.6.0.jar org.apache.spark.launcher.Main org.apache.spark.deploy.master.Master | tr '\0' '\n') # $ARGS now contains the full call to start the master, which I daemonize with nohup SPARK_PUBLIC_DNS=0.0.0.0 nohup "${ARGS[@]}" >> $SPARK_HOME/master.log 2>&1 < /dev/null & 

J'utilise toujours sbin/start-daemon.sh pour démarrer les esclaves, car cela est plus facile que d'appeler nohup dans la commande ssh :

 MASTER=spark://$(hostname -i):7077 while read -r; do ssh -o SsortingctHostKeyChecking=no $REPLY "$SPARK_HOME/sbin/spark-daemon.sh start org.apache.spark.deploy.worker.Worker 1 $MASTER" & done <$SPARK_HOME/conf/slaves # this forks the ssh calls, so wait for them to exit before you logout 

Là! Cela suppose que j'utilise tous les ports et autres éléments par défaut, et que je ne fais pas de bêtises stupides comme de mettre des espaces dans les noms de fichiers, mais je pense que c'est plus propre.