无法在Amazon EMR集群模式运行Spark应用,求SparkSession构建方案
你的问题根源完全出在硬编码了master("local[2]")这个配置上,这在Amazon EMR这种分布式集群环境里是致命错误——直接让你的Spark应用放弃了集群的分布式能力,强制在Driver所在的单个节点以本地多线程模式运行,自然会因为资源不足或者无法并行处理数据而卡住/失败,而本地机器数据量小,所以能快速跑完。
正确的SparkSession构建方式
在EMR集群上,你绝对不应该在代码里指定master参数,EMR会自动通过YARN集群管理器为你分配资源。正确的构建代码应该是这样的:
val spark = SparkSession.builder .appName("Graph Creation") // 调整shuffle分区数,别用1!本地测试用1没问题,但分布式环境下会拖垮性能 .config("spark.sql.shuffle.partitions", "64") // 指定EMR可访问的分布式存储路径,比如S3或者HDFS,别用本地路径 .config("spark.sql.warehouse.dir", "s3://your-bucket-name/warehouse-path") // 如果需要对接EMR自带的Hive元数据,加上这句 .enableHiveSupport() .getOrCreate()
关键配置的详细解释
移除
master("local[2]"):
在EMR上,Spark应用的运行模式由集群控制,默认是YARN模式。硬编码local模式会让所有任务都挤在Driver节点的2个线程里,根本用不到集群的其他Worker节点,数据量大时必然卡住。调整
spark.sql.shuffle.partitions:
你设置的1在分布式环境下是灾难——shuffle操作(比如join、groupBy)会把所有数据塞到一个分区里,单线程处理,速度慢到离谱。建议根据集群的CPU核心数调整,一般设为核心数的2-3倍(比如集群总共有32个核心,就设64),或者根据数据量灵活调整,默认值200也比1好得多。修改
spark.sql.warehouse.dir:
你写的warehouse是本地路径,在EMR集群里,每个节点的本地路径都是独立的,会导致数据无法在节点间共享,甚至Driver节点写完数据后Worker节点找不到。必须指定S3或者HDFS的分布式路径,比如s3://your-bucket/warehouse或者hdfs:///user/hive/warehouse(如果用EMR的Hive仓库)。
额外注意事项
提交应用到EMR时,用spark-submit命令不需要手动指定--master yarn(EMR默认就是YARN模式),但如果要指定的话,也是在提交命令里加,而不是写在代码里。比如:
spark-submit --class com.your.package.GraphCreation --deploy-mode cluster your-app.jar
内容的提问来源于stack exchange,提问作者namrutha

