Spark常见问题汇总
大数据爱好者2017/11/10         
(1)报错信息:
Operation category READ is not supported in state standbyorg.apache.hadoop.ipc.RemoteException(org.apache.hadoop.ipc.StandbyException):
Operation category READ is not supported in state standby
解决方案:
查看执行Spark计算的是否处于standby状态, 用浏览器访问该主机:http://m1:50070, 如果处于standby状态, 则不可在处于StandBy机器运行spark计算,应切执行Spark计算的主机从Standby状态切换到Active状态
(2)问题出现情景:
Spakr集群的所有运行数据在Master重启是都会丢失
解决方案:
配置spark.deploy.recoveryMode选项为ZOOKEEPER
(3)报错信息:
由于Spark在计算的时候会将中间结果存储到/tmp目录,而目前linux又都支持tmpfs,其实就是将/tmp目录挂载到内存当中, 那么这里就存在一个问题,中间结果过多导致/tmp目录写满而出现如下错误
No Space Left on the device(Shuffle临时文件过多)
解决办法:
修改配置文件spark-env.sh,把临时文件引入到一个自定义的目录中去, 即:
export SPARK_LOCAL_DIRS=/home/utoken/datadir/spark/tmp
(4)报错信息:
java.lang.OutOfMemory, unable to create new native thread
Caused by: java.lang.OutOfMemoryError: unable to create new native thread
at java.lang.Thread.start0(Native Method)
at java.lang.Thread.start(Thread.java:640)
解决方案:
上面这段错误提示的本质是Linux操作系统无法创建更多进程,导致出错,并不是系统的内存不足。因此要解决这个问题需要修改Linux允许创建更多的进程,就需要修改Linux最大进程数。
1)修改Linux最大进程数
ulimit -a
2)临时修改允许打开的最大进程数
ulimit -u 65535
3)临时修改允许打开的文件句柄
ulimit -n 65535
4)永久修改Linux最大进程数量
sudo vi /etc/security/limits.d/90-nproc.conf
* soft nproc 60000
root soft nproc unlimited
永久修改用户打开文件的最大句柄数,该值默认1024,一般都会不够,常见错误就是not open file 解决办法:
sudo vi /etc/security/limits.conf
bdata soft nofile 65536
bdata hard nofile 65536
(5)问题出现情景:
Worker节点中的work目录占用许多磁盘空间, 这些是Driver上传到worker的文件, 会占用许多磁盘空间.
解决方案:
需要定时做手工清理. 目录地址:/home/centos/soft/spark/work
(6)问题出现情景:
spark-shell提交Spark Application如何解决依赖库
解决方案:
利用–driver-class-path选项来指定所依赖的jar文件,注意的是–driver-class-path后如果需要跟着多个jar文件的话,jar文件之间使用冒号:来分割。
(7)Spark在发布应用的时候,出现连接不上master
报错信息如下:
INFO AppClient$ClientEndpoint: Connecting to master spark://s1:7077...
WARN ReliableDeliverySupervisor: Association with remote system [akka.tcp://sparkMaster@s1:7077] has failed, address is now gated for [5000] ms. Reason: [Disassociated]
解决方案:
检查所有机器时间是否一致.hosts是否都配置了映射.客户端和服务器端的Scala版本是否一致.Scala版本是否和Spark兼容
(8)开发spark应用程序(和Flume-NG结合时)发布应用时可能会报错
报错信息如下:
ERROR ReceiverSupervisorImpl: Stopped receiver with error: org.jboss.netty.channel.ChannelException: Failed to bind to: /192.168.10.156:18800
ERROR Executor: Exception in task 0.0 in stage 2.0 (TID 70)
org.jboss.netty.channel.ChannelException: Failed to bind to: /192.168.10.156:18800
at org.jboss.netty.bootstrap.ServerBootstrap.bind(ServerBootstrap.java:272)
Caused by: java.net.BindException: Cannot assign requested address
解决方案:
由于spark通过Master发布的时候,会自动选取发送到某一台的worker节点上,所以这里绑定端口的时候,需要选择相应的worker服务器,但是由于我们无法事先了解到,spark发布到哪一台服务器的,所以这里启动报错,是因为在192.168.10.156:18800的机器上面没有启动Driver程序,而是发布到了其他服务器去启动了,所以无法监听到该机器出现问题,所以我们需要设置spark分发包时,发布到所有worker节点机器,或者发布后,我们去寻找发布到了哪一台机器,重新修改绑定IP,重新发布,有一定几率发布成功。
(9)使用Hive on Spark时报错:
ERROR XSDB6: Another instance of Derby may have already booted the database /home/bdata/data/metastore_db.
解决方案:
在使用Hive on Spark模式操作hive里面的数据时,报以上错误,原因是因为HIVE采用了derby这个内嵌数据库作为数据库,它不支持多用户同时访问,解决办法就是把derby数据库换成mysql数据库即可
(10)找不到hdfs集群名字dfscluster
报错信息:
java.lang.IllegalArgumentException: java.net.UnknownHostException: dfscluster
解决办法:
将$HADOOP_HOME/etc/hadoop/hdfs-site.xml文件拷贝到Spark集群的所有主机的$SPARK_HOME/conf目录下,然后重启Spark集群
cd /home/centos/soft/spark/conf/
for i in {201,202,203};
do scp hdfs-site.xml 192.168.179.$i:/home/centos/soft/spark/conf/;
done
(11)在执行yarn集群或者客户端时,报错:
执行指令:
sh $SPARK_HOME/bin/spark-sql --master yarn-client
报如下错误:
Exception in thread "main" java.lang.Exception: When running with master 'yarn-client' either HADOOP_CONF_DIR or YARN_CONF_DIR must be set in the environment.
解决办法:
根据提示,配置HADOOP_CONF_DIR or YARN_CONF_DIR的环境变量即可, 在spark-env.sh文件中配置以下几项:
export HADOOP_HOME=/u01/hadoop-2.6.1
export HADOOP_CONF_DIR=$HADOOP_HOME/etc/hadoop
PATH=$PATH:$HIVE_HOME/bin:$HADOOP_HOME/bin
(12)提交spark计算任务时,报错:
报错信息如下:
Job aborted due to stage failure: Task 3 in stage 0.0 failed 4 times, most recent failure: Lost task 3.3 in
[org.apache.spark.scheduler.TaskSchedulerImpl]-[ERROR] Lost executor 0 on 192.168.10.38: remote Rpc client disassociated
[org.apache.spark.scheduler.TaskSchedulerImpl]-[ERROR] Lost executor 1 on 192.168.10.38: remote Rpc client disassociated
[org.apache.spark.scheduler.TaskSchedulerImpl]-[ERROR] Lost executor 2 on 192.168.10.38: remote Rpc client disassociated
[org.apache.spark.scheduler.TaskSchedulerImpl]-[ERROR] Lost executor 3 on 192.168.10.38: remote Rpc client disassociated
[org.apache.spark.scheduler.TaskSetManager]-[ERROR] Task 3 in stage 0.0 failed 4 times; aborting job
Exception in thread "main" org.apache.spark.SparkException : Job aborted due to stage failure: Task 3 in stage 0.0 failed 4 times, most recent failure: Lost task 3.3 in stage 0.0 (TID 14, 192.168.10.38): ExecutorLostFailure (executor 3 lost)
Driver stacktrace:
at org.apache.spark.scheduler.DAGScheduler.org$apache$spark$scheduler$DAGScheduler$$failJobAndIndependentStages(DAGScheduler.scala:1283)
解决方案:
这里遇到的问题主要是因为数据源数据量过大,而机器的内存无法满足需求,导致长时间执行超时断开的情况,数据无法有效进行交互计算,因此有必要增加内存
(13)启动Spark计算任务:
长时间等待无反应,并且看到服务器上面的web界面有内存和核心数,但是没有分配,报错信息如下:
status.SparkJobMonitor: 2017-01-04 11:53:51,564 Stage-0_0: 0(+1)/1
status.SparkJobMonitor: 2017-01-04 11:53:51,564 Stage-0_0: 0(+1)/1
status.SparkJobMonitor: 2017-01-04 11:53:51,564 Stage-0_0: 0(+1)/1
status.SparkJobMonitor: 2017-01-04 11:53:51,564 Stage-0_0: 0(+1)/1
status.SparkJobMonitor: 2017-01-04 11:53:51,564 Stage-0_0: 0(+1)/1
status.SparkJobMonitor: 2017-01-04 11:53:51,564 Stage-0_0: 0(+1)/1
日志信息显示:
WARN TaskSchedulerImpl: Initial job has not accepted any resources; check your cluster UI to ensure that workers are registered and have sufficient resources
解决方案:
出现上面的问题主要原因是因为我们通过参数spark.executor.memory设置的内存过大,已经超过了实际机器拥有的内存,故无法执行,需要等待机器拥有足够的内存后,才能执行任务,可以减少任务执行内存,设置小一些即可
(14)内存不足或数据倾斜导致Executor Lost(spark-submit提交)
报错信息如下:
TaskSetManager: Lost task 1.0 in stage 6.0 (TID 100, 192.168.10.37): java.lang.OutOfMemoryError: Java heap space
INFO BlockManagerInfo: Added broadcast_8_piece0 in memory on 192.168.10.37:57139 (size: 42.0 KB, free: 24.2 MB)
INFO BlockManagerInfo: Added broadcast_8_piece0 in memory on 192.168.10.38:53816 (size: 42.0 KB, free: 24.2 MB)
INFO TaskSetManager: Starting task 3.0 in stage 6.0 (TID 102, 192.168.10.37, ANY, 2152 bytes)
WARN TaskSetManager: Lost task 1.0 in stage 6.0 (TID 100, 192.168.10.37): java.lang.OutOfMemoryError: Java heap space
at java.io.BufferedOutputStream.<init>(BufferedOutputStream.java:76)
at java.io.BufferedOutputStream.<init>(BufferedOutputStream.java:59)
at org.apache.spark.sql.execution.UnsafeRowSerializerInstance$$anon$2.<init>(UnsafeRowSerializer.scala:55)
ERROR TaskSchedulerImpl: Lost executor 6 on 192.168.10.37: remote Rpc client disassociated
INFO TaskSetManager: Re-queueing tasks for 6 from TaskSet 6.0
WARN ReliableDeliverySupervisor: Association with remote system [akka.tcp://sparkExecutor@192.168.10.37:42250] has failed, address is now gated for [5000] ms. Reason: [Disassociated]
WARN TaskSetManager: Lost task 3.0 in stage 6.0 (TID 102, 192.168.10.37): ExecutorLostFailure (executor 6 lost)
INFO DAGScheduler: Executor lost: 6 (epoch 8)
INFO BlockManagerMasterEndpoint: Trying to remove executor 6 from BlockManagerMaster.
INFO BlockManagerMasterEndpoint: Removing block manager BlockManagerId(6, 192.168.10.37, 57139)
INFO BlockManagerMaster: Removed 6 successfully in removeExecutor
INFO AppClient$ClientEndpoint: Executor updated: app-20160115142128-0001/6 is now EXITED (Command exited with code 52)
INFO SparkDeploySchedulerBackend: Executor app-20160115142128-0001/6 removed: Command exited with code 52
INFO SparkDeploySchedulerBackend: Asked to remove non-existent executor 6
org.apache.spark.SparkException: Job aborted due to stage failure: Task 0 in stage 6.0 failed 4 times, most recent failure: Lost task 0.3 in stage 6.0 (TID 142, 192.168.10.36): ExecutorLostFailure (executor 4 lost)
WARN TaskSetManager: Lost task 4.1 in stage 6.0 (TID 137, 192.168.10.38): java.lang.OutOfMemoryError: GC overhead limit exceeded
解决办法:
由于我们在执行Spark任务是,读取所需要的原数据,数据量太大,导致在Worker上面分配的任务执行数据时所需要的内存不够,直接导致内存溢出了,所以我们有必要增加Worker上面的内存来满足程序运行需要。 在Spark Streaming或者其他spark任务中,会遇到在Spark中常见的问题,典型如Executor Lost相关的问题(shuffle fetch失败,Task失败重试等)。这就意味着发生了内存不足或者数据倾斜的问题。这个目前需要考虑如下几个点以获得解决方案:
A.相同资源下,增加partition数可以减少内存问题。 原因如下:通过增加partition数,每个task要处理的数据少了,同一时间内,所有正在运行的task要处理的数量少了很多,所有Executor占用的内存也变小了。这可以缓解数据倾斜以及内存不足的压力。 B.关注shuffle read阶段的并行数。例如reduce, group 之类的函数,其实他们都有第二个参数,并行度(partition数),只是大家一般都不设置。不过出了问题再设置一下,也不错。 C.给一个Executor核数设置的太多,也就意味着同一时刻,在该Executor的内存压力会更大,GC也会更频繁。我一般会控制在3个左右。然后通过提高Executor数量来保持资源的总量不变。
(15) Spark Streaming 和kafka整合
报错信息如下:
OffsetOutOfRangeException
解决方案:
如果和kafka消息中间件结合使用,请检查消息体是否大于默认设置1m,如果大于,则需要设置fetch.message.max.bytes=1m, 这里需要把值设置大些
(16)报错信息:
java.io.IOException : Could not locate executable null\bin\winutils.exe in the Hadoop binaries.(spark sql on hive 任务引发HiveContext NullPointerException)
解决办法:
在开发hive和Spark整合的时候,如果是Windows系统,并且没有配置HADOOP_HOME的环境变量,那么可能找不到winutils.exe这个工具,由于使用hive时,对该命令有依赖,所以不要忽视该错误,否则将无法创建HiveContext,一直报Exception in thread “main” java.lang.RuntimeException: java.lang.NullPointerException 因此,解决该办法有两个方式
方案A:
把任务打包成jar,上传到服务器上面,服务器是配置过HADOOP_HOME环境变量的,并且不需要依赖winutils,所以只需要通过spark-submit方式提交即可,如:
spark-submit --class com.pride.hive.HiveOnSparkTest --master spark://bdata4:7077 spark-simple-1.0.jar
方案B:
解决winutils.exe命令不可用问题,配置Windows上面HADOOP_HOME的环境变量,或者在程序最开始的地方设置HADOOP_HOME的属性配置,这里需要注意,由于最新版本已经没有winutils这些exe命令了,我们需要在其他地方下载该命令放入HADOOP的bin目录下,当然也可以直接配置下载项目的环境变量,变量名一定要是HADOOP_HOME才行
下载地址:
https://github.com/srccodes/hadoop-common-2.2.0-bin/archive/master.zip
任何项目都生效,需要配置Windows的环境变量,如果只在程序中生效可在程序中配置即可,如:
//用于解决Windows下找不到winutils.exe命令
System. setProperty("hadoop.home.dir", "E:\\Software\\hadoop-common-2.2.0-bin" );
(17)报错信息:
Exception in thread “main” org.apache.hadoop.security.AccessControlException : Permission denied: user=Administrator, access=WRITE, inode=”/data”:bdata:supergroup:drwxr-xr-x
解决办法
1.在系统的环境变量或JVM变量里面添加HADOOP_USER_NAME,如程序中添加: System.setProperty(“HADOOP_USER_NAME”, “bdata”);, 这里的值就是以后会运行HADOOP上的Linux的用户名,如果是eclipse,则修改完重启eclipse,不然可能不生效 2.修改有问题的目录权限
hadoop fs -chmod 755 /tmp
并hive-site.xml文件中增加以下配置
<property>
<name>hive.scratch.dir.permission</name>
<value>755</value>
</property>
(18)运行Spark-SQL报错:
org.apache.spark.sql.AnalysisException: unresolved operator 'Project
解决办法:
在Spark-sql和hive结合时或者单独Spark-sql,运行某些sql语句时,偶尔出现上面错误,那么我们可以检查一下sql的问题,这里遇到的问题是嵌套语句太多,导致spark无法解析,所以需要修改sql或者改用其他方式处理;特别注意该语句可能在hive里面没有错误,spark才会出现的一种错误。
(19)报错信息如下:
org.apache.spark.SparkException: Only one SparkContext may be running in this JVM (see SPARK-2243). To ignore this error, set spark.driver.allowMultipleContexts = true.
解决方案:
使用Use this constructor JavaStreamingContext(sparkContext: JavaSparkContext, batchDuration: Duration) 替代 new JavaStreamingContext(sparkConf, Durations.seconds(5))
(20)报错信息如下:
java.lang.IllegalArgumentException: requirement failed: No output operations registered, so nothing to execute
解决方案:
tranformation最后一步产生的那个RDD必须有相应Action操作,例如massages.print()等
(21)报错信息如下:
ERROR ApplicationMaster: SparkContext did not initialize after waiting for 100000 ms. Please check earlier log output for errors. Failing the application
解决方案:
资源不能分配过大,或者没有把.setMaster(“local[*]”)去掉
(22)报错信息如下:
java.util.regex.PatternSyntaxException: Dangling meta character '?' near index 0
解决方案:
元字符记得转义
(23)报错信息如下:
Exception in thread "main" java.lang.NoClassDefFoundError: org/apache/hadoop/fs/FSDataInputStream
解决方案:
编译spark用了hadoop-provided参数,导致缺少hadoop相关包
(24)报错信息如下:
org.apache.spark.SparkException: Task failed while writing rows Caused by: org.elasticsearch.hadoop.rest.EsHadoopInvalidRequest: null
解决方案:
ES负载过高,修复ES
(25)报错信息如下:
org.apache.spark.SparkException: Task failed while writing rows scala.MatchError: Buffer(10.113.80.29, None) (of class scala.collection.convert.Wrappers$JListWrapper)
解决方案:
ES数据在sparksql类型转化时不兼容,可通过EsSpark.esJsonRDD以字符串形式取ES数据,再把rdd转换成dataframe
(26)报错信息如下:
SparkListenerBus has already stopped! Dropping event SparkListenerStageCompleted
解决方案:
集群资源不够,确保真实剩余内存大于spark job申请的内存
(27)报错信息如下:
ExecutorLostFailure (executor 3 exited caused by one of the running tasks) Reason: Container killed by YARN for exceeding memory limits. 61.0 GB of 61 GB physical memory used
解决方案:
配置项spark.storage.memoryFraction默认值为0.6, 应加大spark.storage.memoryFraction的系数
(28)问题如下:
如何定位spark的数据倾斜
解决方案:
在Spark Web UI看一下当前stage各个task分配的数据量以及执行时间,根据stage划分原理定位代码中shuffle类算子
(29)报错信息如下:
如何解决spark数据倾斜
解决方案:
过滤少数导致倾斜的key(仅限于抛弃的Key对作业影响很小)
提高shuffle操作并行度(提升效果有限)
两阶段聚合(局部聚合+全局聚合),先对相同的key加前缀变成多个key,局部shuffle后再去掉前缀,再次进行全局shuffle(仅适用于聚合类的shuffle操作,效果明显,对于join类的shuffle操作无效),
将reduce join转为map join,将小表进行广播,对大表map操作,遍历小表数据(仅适用于大小表或RDD情况)
使用随机前缀和扩容RDD进行join,对其中一个RDD每条数据打上n以内的随机前缀,用flatMap算子对另一个RDD进行n倍扩容并扩容后的每条数据依次打上0~n的前缀,最后将两个改造key后的RDD进行join(能大幅缓解join类型数据倾斜,需要消耗巨额内存)
(30)报错信息如下:
org.apache.spark.SparkException: Failed to get broadcast_790_piece0 of broadcast_790
解决方案:
删除spark-defaults.conf文件中spark.cleaner.ttl的配置
(31)报错信息如下:
MapperParsingException[Malformed content, must start with an object
解决方案:
采用接口JavaEsSpark.saveJsonToEs,因为saveToEs只能处理对象不能处理字符串
(32)报错信息如下:
java.util.concurrent.TimeoutException: Cannot receive any reply in 120 seconds
解决方案:
确保所有节点之间能够免密码登录
确保所在的主机满足spark-env.sh中分配的CPU个数,若spark-env.sh中分配的CPU个数为一个,而master和worker在同一部主机上,则该主机需最少分配2个CPU
(33)报错信息如下:
Exception in thread “main” org.apache.spark.SparkException: Yarn application has already ended! It might have been killed or unable to launch application master.
解决方案:
出现此类问题有很多种, 当时遇到这问题的因为是在spark未改动的情况下, 更换了Hive的版本导致版本不对出现了此问题, 解决此问题的方法是:
再次运行spark计算, 查看日志中Hive的版本, 检查当前Hive是否与Spark日志中的Hive版本一致
若Hive版本不一致, 则删除现有的Hive, 并删除MySQL中Hive的元数据(若使用MySQL元数据库), HDFS上hive, tmp, user目录下的数据
安装与Spark日志中版本匹配的Hive\
看完这篇文章的人大多学习了更多课程>>
