web-dev-qa-db-fra.com

Faire fonctionner ensemble Spark, Python et MongoDB

J'ai du mal à assembler correctement ces composants. J'ai Spark installé et fonctionne avec succès, je peux exécuter des tâches localement, de manière autonome et également via YARN. J'ai suivi les étapes conseillées (au meilleur de ma connaissance) ici et ici

Je travaille sur Ubuntu et les différentes versions de composants que j'ai sont

J'ai eu quelques difficultés à suivre les différentes étapes telles que les pots à ajouter à quel chemin, donc ce que j'ai ajouté sont

  • dans /usr/local/share/hadoop-2.6.1/share/hadoop/mapreduce J'ai ajouté mongo-hadoop-core-1.5.0-SNAPSHOT.jar
  • les variables d'environnement suivantes
    • export HADOOP_HOME="/usr/local/share/hadoop-2.6.1"
    • export PATH=$PATH:$HADOOP_HOME/bin
    • export SPARK_HOME="/usr/local/share/spark-1.5.1-bin-hadoop2.6"
    • export PYTHONPATH="/usr/local/share/mongo-hadoop/spark/src/main/python"
    • export PATH=$PATH:$SPARK_HOME/bin

Mon programme Python est basique

from pyspark import SparkContext, SparkConf
import pymongo_spark
pymongo_spark.activate()

def main():
    conf = SparkConf().setAppName("pyspark test")
    sc = SparkContext(conf=conf)
    rdd = sc.mongoRDD(
        'mongodb://username:password@localhost:27017/mydb.mycollection')

if __name__ == '__main__':
    main()

Je l'exécute en utilisant la commande

$SPARK_HOME/bin/spark-submit --driver-class-path /usr/local/share/mongo-hadoop/spark/build/libs/ --master local[4] ~/sparkPythonExample/SparkPythonExample.py

et je reçois la sortie suivante à la suite

Traceback (most recent call last):
  File "/home/me/sparkPythonExample/SparkPythonExample.py", line 24, in <module>
    main()
  File "/home/me/sparkPythonExample/SparkPythonExample.py", line 17, in main
    rdd = sc.mongoRDD('mongodb://username:password@localhost:27017/mydb.mycollection')
  File "/usr/local/share/mongo-hadoop/spark/src/main/python/pymongo_spark.py", line 161, in mongoRDD
    return self.mongoPairRDD(connection_string, config).values()
  File "/usr/local/share/mongo-hadoop/spark/src/main/python/pymongo_spark.py", line 143, in mongoPairRDD
    _ensure_pickles(self)
  File "/usr/local/share/mongo-hadoop/spark/src/main/python/pymongo_spark.py", line 80, in _ensure_pickles
    orig_tb)
py4j.protocol.Py4JError

Selon ici

Cette exception est déclenchée lorsqu'une exception se produit dans le code client Java. Par exemple, si vous essayez d'extraire un élément d'une pile vide. L'instance de l'exception Java levée est stockée dans le membre Java_exception.

En regardant le code source de pymongo_spark.py Et la ligne générant l'erreur, il est dit

"Erreur lors de la communication avec la JVM. Le pot MongoDB Spark est-il sur le CLASSPATH de Spark?:"

Donc, en réponse, j'ai essayé de m'assurer que les bons pots étaient passés, mais je pourrais faire tout cela mal, voir ci-dessous

$SPARK_HOME/bin/spark-submit --jars /usr/local/share/spark-1.5.1-bin-hadoop2.6/lib/mongo-hadoop-spark-1.5.0-SNAPSHOT.jar,/usr/local/share/spark-1.5.1-bin-hadoop2.6/lib/mongo-Java-driver-3.0.4.jar --driver-class-path /usr/local/share/spark-1.5.1-bin-hadoop2.6/lib/mongo-Java-driver-3.0.4.jar,/usr/local/share/spark-1.5.1-bin-hadoop2.6/lib/mongo-hadoop-spark-1.5.0-SNAPSHOT.jar --master local[4] ~/sparkPythonExample/SparkPythonExample.py

J'ai importé pymongo dans le même programme python pour vérifier que je peux au moins accéder à MongoDB en utilisant cela, et je le peux.

Je sais qu'il y a pas mal de pièces mobiles ici, donc si je peux fournir des informations plus utiles, faites le moi savoir.

34
Philip O'Brien

Mises à jour :

2016-07-04

Depuis la dernière mise à jour MongoDB Spark Connector a beaucoup évolué. Il fournit des binaires à jour et une API basée sur la source de données mais il utilise la configuration SparkConf donc elle est subjectivement moins flexible que la Stratio/Spark-MongoDB.

2016-03-30

Depuis la réponse d'origine, j'ai trouvé deux façons différentes de se connecter à MongoDB depuis Spark:

Alors que le premier semble relativement immature, le second semble être un bien meilleur choix qu'un connecteur Mongo-Hadoop et fournit une API Spark SQL).

# Adjust Scala and package version according to your setup
# although officially 0.11 supports only Spark 1.5
# I haven't encountered any issues on 1.6.1
bin/pyspark --packages com.stratio.datasource:spark-mongodb_2.11:0.11.0
df = (sqlContext.read
  .format("com.stratio.datasource.mongodb")
  .options(Host="mongo:27017", database="foo", collection="bar")
  .load())

df.show()

## +---+----+--------------------+
## |  x|   y|                 _id|
## +---+----+--------------------+
## |1.0|-1.0|56fbe6f6e4120712c...|
## |0.0| 4.0|56fbe701e4120712c...|
## +---+----+--------------------+

Il semble être beaucoup plus stable que mongo-hadoop-spark, Prend en charge le pushdown de prédicat sans configuration statique et fonctionne simplement.

La réponse d'origine :

En effet, il y a pas mal de pièces mobiles ici. J'ai essayé de le rendre un peu plus gérable en créant une image Docker simple qui correspond à peu près à la configuration décrite (j'ai cependant omis les bibliothèques Hadoop pour plus de brièveté). Vous pouvez trouver source complète sur GitHub ( DOI 10.5281/zenodo.47882 ) et le construire à partir de zéro:

git clone https://github.com/zero323/docker-mongo-spark.git
cd docker-mongo-spark
docker build -t zero323/mongo-spark .

ou téléchargez une image que j'ai poussée vers Docker Hub pour que vous puissiez simplement docker pull zero323/mongo-spark):

Démarrer les images:

docker run -d --name mongo mongo:2.6
docker run -i -t --link mongo:mongo zero323/mongo-spark /bin/bash

Démarrez PySpark Shell en passant --jars Et --driver-class-path:

pyspark --jars ${JARS} --driver-class-path ${SPARK_DRIVER_EXTRA_CLASSPATH}

Et enfin voyez comment cela fonctionne:

import pymongo
import pymongo_spark

mongo_url = 'mongodb://mongo:27017/'

client = pymongo.MongoClient(mongo_url)
client.foo.bar.insert_many([
    {"x": 1.0, "y": -1.0}, {"x": 0.0, "y": 4.0}])
client.close()

pymongo_spark.activate()
rdd = (sc.mongoRDD('{0}foo.bar'.format(mongo_url))
    .map(lambda doc: (doc.get('x'), doc.get('y'))))
rdd.collect()

## [(1.0, -1.0), (0.0, 4.0)]

Veuillez noter que mongo-hadoop semble fermer la connexion après la première action. Ainsi, appeler par exemple rdd.count() après la collecte lèvera une exception.

Sur la base de différents problèmes que j'ai rencontrés lors de la création de cette image, j'ai tendance à croire que passe mongo-hadoop-1.5.0-SNAPSHOT.jar Et mongo-hadoop-spark-1.5.0-SNAPSHOT.jar aux deux --jars et --driver-class-path est la seule exigence difficile .

Remarques :

  • Cette image est vaguement basée sur jaceklaskowski/docker-spark alors assurez-vous d'envoyer du bon karma à @ jacek-laskowski si cela vous aide.
  • Si vous n'avez pas besoin d'une version de développement incluant nouvelle API alors utiliser --packages Est probablement une meilleure option.
15
zero323

Pouvez-vous essayer d'utiliser --package option au lieu de --jars ... dans votre commande spark-submit:

spark-submit --packages org.mongodb.mongo-hadoop:mongo-hadoop-core:1.3.1,org.mongodb:mongo-Java-driver:3.1.0 [REST OF YOUR OPTIONS]

Certains de ces fichiers jar ne sont pas des fichiers Uber et ont besoin de plus de dépendances à télécharger avant de pouvoir fonctionner.

3
asaad

Bonne chance!

@see https://github.com/mongodb/mongo-hadoop/wiki/Spark-Usage

from pyspark import SparkContext, SparkConf

import pymongo_spark
# Important: activate pymongo_spark.
pymongo_spark.activate()


def main():
    conf = SparkConf().setAppName("pyspark test")
    sc = SparkContext(conf=conf)

    # Create an RDD backed by the MongoDB collection.
    # This RDD *does not* contain key/value pairs, just documents.
    # If you want key/value pairs, use the mongoPairRDD method instead.
    rdd = sc.mongoRDD('mongodb://localhost:27017/db.collection')

    # Save this RDD back to MongoDB as a different collection.
    rdd.saveToMongoDB('mongodb://localhost:27017/db.other.collection')

    # You can also read and write BSON:
    bson_rdd = sc.BSONFileRDD('/path/to/file.bson')
    bson_rdd.saveToBSON('/path/to/bson/output')

if __name__ == '__main__':
    main()
0
larryhu

J'avais ce même problème hier. A pu le réparer en plaçant mongo-Java-driver.jar dans $HADOOP_HOME/lib et mongo-hadoop-core.jar et mongo-hadoop-spark.jar dans $HADOOP_HOME/spark/classpath/emr (Ou tout autre dossier qui se trouve dans le $SPARK_CLASSPATH).

Faites-moi savoir si cela vous a été utile.

0
Dhruvkaran Mehta