从本地IntelliJ向VirtualBox中Hortonworks Sandbox提交Spark任务失败求助
解决本地IntelliJ向Hortonworks Sandbox提交Spark任务失败的问题
Hey,我之前帮不少人踩过本地IDE向Hortonworks Sandbox提交Spark任务的坑,结合你的情况,给你梳理下最可能的几个问题点和对应的解决办法:
1. 先确认网络与集群服务状态
- 首先确保本地机器能ping通Sandbox虚拟机的IP:你可以在VirtualBox的Sandbox控制台里找到它的IP(比如常见的
192.168.56.101),在本地终端执行ping <sandbox-ip>,如果不通,先调整VirtualBox的网络模式(推荐用桥接模式,让虚拟机和本地在同一网段)。 - 登录Sandbox的Ambari管理界面(默认端口8080),检查Spark服务的状态:确保Spark Master和Worker节点都处于
Running状态,如果服务没启动,先手动启动。
2. 匹配Spark版本 + 配置正确的集群连接信息
这是最容易踩的坑!本地项目的Spark版本必须和Sandbox里的完全一致,否则会出现兼容性错误。
- 先查Sandbox的Spark版本:登录Sandbox终端,执行
spark-submit --version,记下版本号(比如2.4.0)。 - 在IntelliJ的项目里,修改构建文件(Maven的pom.xml或SBT的build.sbt),把Spark依赖的版本改成和Sandbox一致的。
- 补全你的SparkConf配置,关键要指定集群Master地址和本地Driver的可访问IP(因为Sandbox的Worker需要回连本地Driver):
val conf = new SparkConf() .setAppName("Simple Application") .setMaster("spark://<sandbox-ip>:7077") // 替换成你的Sandbox Spark Master地址,默认端口7077 .set("spark.driver.host", "<你的本地机器IP>") // 比如192.168.56.1,必须是Sandbox能访问到的IP
3. 修正文件路径问题
你代码里的file:///tmp/words.txt是本地机器的路径,但提交到集群后,Worker节点会去自己的/tmp目录找这个文件,肯定找不到!有两种解决方式:
- 把文件上传到Sandbox的HDFS:登录Sandbox终端,执行
hdfs dfs -put /path/to/local/words.txt /tmp/,然后代码里的路径改成hdfs://<sandbox-ip>:8020/tmp/words.txt(HDFS默认端口8020)。 - 如果只是想本地测试,可以把Master设置成
local[*],这样任务会在本地运行,不用提交到集群。
4. 检查IntelliJ的运行配置
- 确保你的Run Configuration是
Application类型,主类选择HelloWorld。 - 运行前先执行构建工具的
clean package命令(Maven:mvn clean package,SBT:sbt clean package),确保所有依赖都正确下载,没有缺失或冲突。
5. 防火墙端口排查
- 本地机器的防火墙要开放Spark Driver的端口(默认是随机端口,你也可以在SparkConf里用
spark.driver.port指定一个固定端口,然后开放它)。 - Sandbox虚拟机也要开放Spark Master的7077端口、Worker的端口,以及HDFS的8020端口(如果用HDFS的话)。
给你一个完整的可参考代码示例:
import org.apache.spark.{SparkConf, SparkContext} object HelloWorld { def main(args: Array[String]): Unit = { // 注意替换成你的Sandbox IP和本地IP val hdfsFile = "hdfs://192.168.56.101:8020/tmp/words.txt" val conf = new SparkConf() .setAppName("Simple Application") .setMaster("spark://192.168.56.101:7077") .set("spark.driver.host", "192.168.56.1") val sc = new SparkContext(conf) val textData = sc.textFile(hdfsFile).cache() val countA = textData.filter(_.contains("a")).count() val countB = textData.filter(_.contains("b")).count() println(s"包含a的行数:$countA,包含b的行数:$countB") sc.stop() } }
内容的提问来源于stack exchange,提问作者JaviOverflow
相关产品推荐
相关产品推荐

