Spark 2.2.1本地模式与独立集群模式Java应用运行故障排查
兄弟,我之前在Windows上折腾Spark standalone的时候踩过不少坑,结合你的情况——local模式正常,切到集群模式就报JRE相关错误,大概率是这几个问题之一,咱们一个个来排查:
1. 集群节点与本地Eclipse的JRE环境不匹配
这是Windows上最常见的坑!local模式下,你的应用用的是Eclipse自带或者你配置的JRE/JDK,但Spark集群的master和worker节点用的是系统环境变量里的JAVA_HOME指定的JRE,一旦版本不一致(比如你Eclipse用的是JDK 1.8,集群用的是JDK 1.7),或者JRE路径带空格(比如C:\Program Files\Java),就会触发类加载错误或者JRE相关报错。
解决方法:
- 打开Spark安装目录下的
conf/spark-env.cmd(如果没有就复制spark-env.cmd.template重命名),设置JAVA_HOME为你Eclipse用的那个JDK的绝对路径,而且要避开空格,比如把C:\Program Files\Java\jdk1.8.0_201写成C:\Progra~1\Java\jdk1.8.0_201(Windows下用短路径替代带空格的路径)。 - 重启Spark master和worker节点,确保配置生效。
2. 应用依赖未正确分发到集群
local模式下Eclipse会把所有依赖jar都加载到本地JVM里,但切换到standalone模式时,worker节点需要获取你的应用代码和依赖才能执行任务。如果你直接在Eclipse里运行而没有打包成可执行jar,worker节点会找不到你的类或者依赖库,进而报JRE相关的类找不到错误。
解决方法:
- 把你的Java应用打包成Fat Jar(包含所有依赖的可执行jar),Eclipse里可以用Maven的
maven-assembly-plugin或者Gradle的shadowJar插件来构建。 - 用Spark官方的
spark-submit命令提交jar包,比如:spark-submit --class com.yourpackage.YourMainClass --master spark://192.168.1.5:7077 your-app-fat.jar - 如果一定要在Eclipse里运行,需要在SparkConf里设置
spark.executor.extraClassPath,把你的依赖jar路径(绝对路径,Windows下用;分隔)告诉worker节点,但这种方式在Windows下容易出路径问题,更推荐打包成Fat Jar。
3. Windows防火墙挡住了集群通信
Spark的master、worker和driver之间需要互相通信,比如master的7077端口、driver的随机端口、worker的通信端口,如果Windows防火墙没放行这些端口,就会导致连接失败,进而触发JRE相关的超时或连接错误。
解决方法:
- 先临时关闭Windows防火墙试试,如果能正常运行,说明是防火墙的问题。
- 永久解决的话,把Spark相关的端口加入防火墙允许列表:7077(master服务端口)、8080(master webUI)、4040(driver webUI),还有worker的默认端口(8081),另外还要允许Spark的java进程通过防火墙。
4. Spark集群状态异常
先确认你的Spark standalone集群是不是正常运行的:
- 打开master的webUI(默认
http://192.168.1.5:8080),看看有没有worker节点注册上来,如果worker列表为空,说明worker没启动或者注册失败。 - 检查master和worker的启动控制台输出,有没有报错信息(比如worker无法连接master,或者JRE路径错误)。
解决方法:
- 如果worker没启动,运行Spark安装目录下的
bin/spark-worker.cmd,并确保spark-env.cmd里的SPARK_MASTER_URL设置为spark://192.168.1.5:7077。 - 如果worker注册失败,检查master的IP是不是正确(别用localhost或者127.0.0.1,要用局域网IP),还有master和worker是不是在同一个局域网里。
5. Eclipse运行配置的Driver主机绑定问题
Windows下Spark有时候会自动把driver绑定到127.0.0.1,导致worker节点无法连接回driver,进而报找不到driver或者类加载失败的错误。
解决方法:
- 在你的SparkConf里手动设置driver的主机IP,比如:
SparkConf conf = new SparkConf() .setMaster("spark://192.168.1.5:7077") .setAppName("YourAppName") .set("spark.driver.host", "192.168.1.x"); // 这里填你的本机局域网IP - 确保这个IP能被worker节点访问到(比如ping一下试试)。
内容的提问来源于stack exchange,提问作者Aleksey N Yakushev

