Apache Spark classpath de l'est construit dynamiquement (à adapter par l'utilisateur de l'application du code) ce qui la rend vulnérable à de telles questions. @user7337271's réponse est correcte, mais il y a d'autres préoccupations, selon le gestionnaire du cluster ("master") que vous utilisez.
Tout d'abord, une Étincelle de l'application se compose des éléments suivants (chacun est séparé de la JVM, donc potentiellement contient des classes différentes dans son classpath):
-
Pilote: c'est votre demande de création d'un
SparkSession
(ou SparkContext
) et la connexion à un cluster manager pour effectuer le travail réel
-
Le Gestionnaire de Cluster: sert de "point d'entrée" pour le cluster, en charge de l'allocation des exécuteurs pour chaque application. Il ya plusieurs différents types de prise en charge dans Spark: autonome, de FILÉS et de Mesos, que nous allons décrire ci-dessous.
-
Les exécuteurs: ce sont les processus sur les nœuds du cluster, en effectuant le travail réel (l'exécution de l'Étincelle tâches)
Le relationsip entre elles est décrite dans ce diagramme de Apache Spark du cluster en mode aperçu:
Maintenant - les classes à résider dans chacune de ces composantes?
Cela peut être répondu par le diagramme suivant:
Nous allons analyser que lentement:
Spark Code sont Étincelle des bibliothèques. Ils doivent exister dans TOUS les trois composantes comprennent la colle qui permettent d'Allumage de réaliser la communication entre eux. Par la voie d'Allumage auteurs ont fait une décision de conception pour inclure le code pour TOUS les composants TOUS les composants (par exemple, pour inclure le code qui doit s'exécuter uniquement dans Exécuteur testamentaire de pilote de trop) pour simplifier ce - de sorte que l'Étincelle du "gras bocal" (dans les versions jusqu'à 1,6), ou "archive" (dans la version 2.0, les détails ci-dessous) contient le code nécessaire pour tous les composants et devrait être disponible dans tous les d'entre eux.
Pilote-Seul le Code c'est le code de l'utilisateur qui ne comprend pas ce qui doit être utilisée sur les Exécuteurs testamentaires, c'est à dire un code qui n'est pas utilisée dans toutes les transformations des RDD / DataFrame / Dataset. Ce n'est pas forcément à se séparer de l'distribué le code de l'utilisateur, mais il peut l'être.
Distribué Code c'est le code de l'utilisateur qui est compilé avec le code de pilote, mais aussi doit être exécuté sur les Exécuteurs testamentaires - tout ce que le réel transformations doivent être inclus dans ce pot(s).
Maintenant que nous avons obtenu que la droite, comment pouvons-nous obtenir les classes à charger correctement dans chaque composante, et quelles sont les règles à suivre?
-
Spark Code: comme les réponses précédentes de l'état, vous devez utiliser le même Scala et Étincelle versions dans toutes les composantes.
1.1 Autonome de mode, il y a une "pré-existants" l'Étincelle de l'installation pour les applications (les pilotes) peuvent se connecter. Cela signifie que tous les pilotes doivent utiliser la même Étincelle de la version en cours d'exécution sur le maître et les exécuteurs.
1.2 En FIL / Mesos, chaque application peut utiliser une autre Étincelle version, mais tous les composants de la même application doit utiliser le même. Cela signifie que si vous avez utilisé la version X de compiler et d'emballage de votre pilote de l'application, vous devez fournir la même version lors du démarrage de l'SparkSession (par ex. via l' spark.yarn.archive
ou spark.yarn.jars
paramètres lors de l'utilisation de FIL). Les pots / archive que vous fournissez doit inclure tous Étincelle dépendances (y compris les dépendances transitives), et il sera expédié par le gestionnaire du cluster de chaque exécuteur lorsque l'application démarre.
Code du pilote: c'est entièrement de pilote de code peut être expédié comme un tas de pots ou de "gras bocal", tant qu'il inclut tous Étincelle dépendances + tous le code de l'utilisateur
Distribué Code: en plus d'être présent sur le Conducteur, ce code doit être expédiée à exécuteurs testamentaires (encore une fois, avec l'ensemble de ses dépendances transitives). Ceci est fait en utilisant l' spark.jars
paramètre.
Pour résumer, voici une proposition de démarche pour la construction et le déploiement d'une Application Spark (dans ce cas - à l'aide de FIL):
- Créer une bibliothèque avec votre code, tout à la fois comme un "régulier" pot (avec une .pom fichier décrivant ses dépendances) et comme un "gros bocal" (avec toutes ses dépendances transitives inclus).
- La création d'un pilote de l'application, avec la compilation des dépendances sur votre distribués code de la bibliothèque et sur Apache Spark (avec une version spécifique)
- Package de l'application chauffeur dans un gros bocal à être déployé à pilote
- Passer de la version de votre code en tant que valeur de
spark.jars
paramètre lors du démarrage de l' SparkSession
- Passer à l'emplacement d'un fichier d'archive (par exemple, gzip) contenant tous les pots en vertu de l'
lib/
le dossier téléchargé Étincelle binaires est la valeur de spark.yarn.archive