在EMR上配置Jupyter通过CQL读取Cassandra数据时遇到ClassNotFoundException问题求助
解决EMR Jupyter中Spark连接Cassandra的ClassNotFoundException问题
看起来你遇到的问题是Spark找不到Cassandra数据源的依赖包,这在EMR的Jupyter环境里很常见——毕竟Jupyter的Spark Kernel启动时机和本地PySpark不太一样,直接在代码里设置环境变量或者Session配置往往不生效。我来给你几个可行的解决方案:
核心原因
你尝试的两种配置方式都有小问题:
- 方式一的
os.environ['PYSPARK_SUBMIT_ARGS']是在Jupyter Kernel启动后才设置的,此时Spark上下文已经初始化完毕,这个配置根本没被读到; - 方式二的SparkSession构建里只加了Cassandra连接配置,但没指定Spark-Cassandra Connector的依赖包,导致Spark找不到
org.apache.spark.sql.cassandra这个数据源类。
解决方案一:修改Jupyter Spark Kernel配置(持久生效)
这是最推荐的方式,修改后每次打开Jupyter Notebook都会自动加载Connector依赖:
- 找到EMR上Jupyter Spark Kernel的配置文件,通常路径是
/opt/jupyterhub/kernels/sparkkernel/kernel.json(不同EMR版本可能略有差异,找不到的话可以用sudo find / -name "kernel.json" | grep spark查找)。 - 编辑这个文件,在
argv列表里添加--packages和Cassandra连接的配置参数,修改后的内容类似:
{ "argv": [ "/usr/bin/python3", "-m", "ipykernel_launcher", "--master", "yarn", "--packages", "datastax:spark-cassandra-connector:2.4.0-s_2.11", "--conf", "spark.cassandra.connection.host=x.x.x.x", "--conf", "spark.cassandra.connection.port=xxxx", "-f", "{connection_file}" ], "display_name": "Spark", "language": "python" }
- 重启Jupyter服务让配置生效:
sudo systemctl restart jupyterhub - 重新打开Notebook,直接执行你的Cassandra读取代码即可。
解决方案二:Notebook内动态重置Spark上下文(临时生效)
如果不想修改全局配置,每次启动Notebook时先重置Spark环境:
# 先停止已存在的Spark上下文(如果有的话) from pyspark.sql import SparkSession if 'spark' in locals() or 'spark' in globals(): spark.stop() # 必须在初始化SparkSession之前设置环境变量 import os os.environ['PYSPARK_SUBMIT_ARGS'] = '--packages datastax:spark-cassandra-connector:2.4.0-s_2.11 --conf spark.cassandra.connection.host=x.x.x.x --conf spark.cassandra.connection.port=xxxx pyspark-shell' # 重新初始化SparkSession spark = SparkSession.builder \ .appName('SparkCassandraApp') \ .config('spark.cassandra.output.consistency.level','ONE') \ .getOrCreate()
注意:这段代码必须放在所有Spark操作的最开头,而且每次重启Notebook都要重新执行一遍。另外,EMR上不建议用.master('local[2]'),去掉这个参数让Spark自动使用YARN集群模式更合适。
解决方案三:EMR集群启动时预装Connector(长期集群使用)
如果这个集群长期需要连接Cassandra,可以在启动EMR集群时通过引导操作预装依赖:
- 创建一个引导脚本
install_cassandra_connector.sh,内容如下:
#!/bin/bash # 运行spark-shell自动下载并缓存Connector依赖 sudo spark-shell --packages datastax:spark-cassandra-connector:2.4.0-s_2.11 --conf spark.cassandra.connection.host=x.x.x.x -e "exit()"
- 启动EMR集群时,在引导操作里添加这个脚本,集群启动后会自动把Connector依赖缓存到集群的Spark环境中,后续Jupyter使用Spark时无需再指定依赖包。
验证与排查
如果还是报错,检查这几点:
- 确认Connector版本和你的Spark、Scala版本匹配:比如Spark 2.4.x对应Connector 2.4.x-s_2.11(Scala 2.11),如果EMR用的是Scala 2.12,要换成对应的Connector版本;
- 确认EMR集群的安全组开放了Cassandra的端口(默认9042),且Cassandra集群的IP能被EMR节点访问;
- 检查你的keyspace和表名拼写是否正确,Cassandra是大小写敏感的(如果创建时用了引号)。
内容的提问来源于stack exchange,提问作者Ben Reber
相关产品推荐
相关产品推荐

