Spark FAQ
本文汇总了使用DLA Spark的常见问题及解决方案。
常见问题
如何处理Spark作业报错:The VirtualCluster's name is invalid or the VirtualCluster's is not in running state?
如何处理Spark作业报错:User %s do not have right permission [ *** ] to resource [ *** ]?
如何处理Spark SQL读JSON外表(包含日志投递自建)时的报错ClassNotFoundException: org.apache.hadoop.hive.serde2.JsonSerDe?
如何处理执行Spark SQL报错:Exception in thread "main" java.io.IOException: No FileSystem for scheme: oss?
常见问题
如何处理Spark作业报错:The VirtualCluster's name is invalid or the VirtualCluster's is not in running state?
常见原因:虚拟集群名称(VcName)没配置,一般是由于该虚拟集群不存在或者该虚拟集群不是在运行中状态
解决方案:您需要填写正确的虚拟集群,如下所示。
如果该错误是DLA控制台作业管理界面报出,请先创建虚拟集群,再提交作业。
如果您使用的不是控制台方式,而是Aliyun OpenAPI、Spark-submit脚本或者Jupyter等,需要检查配置参数VcName对应的需求集群是否未填写或者填写错误。查找可用的虚拟集群名称的方法如下。
登录DLA控制台。
左侧导航栏单击虚拟集群管理。
在虚拟集群列表中选择状态是运行中的虚拟集群的名字。
如何处理Spark作业报错:User %s do not have right permission [ *** ] to resource [ *** ]?
常见原因:当前子账号没有调用该接口的权限。
解决方案如下。
如何处理Spark作业报错:No space left on device?
首先判断报错信息是否是Executor本地内存不足导致的,判断方法是查看SparkUI中Executor的Stderr日志信息。如果是,您可以通过添加如下配置来增加Executor本地盘的大小。
spark.k8s.shuffleVolume.enable: true
spark.dla.local.disk.size: 50Gi
本地盘为ESSD类型,暂时免费,后续会收费。
当前本地盘最大为100Gi。
如果已经配置了100Gi的本地盘,仍然提示空间不足,那么可以考虑增加Executor的数量。
Spark Executor出现Dead怎么处理?
首先进入SparkUI页面,如果Failed Stages的Failure reason中包含Failed to connect to /xx.xx.xx.xx:xxxx或者在SparkUI->Executors页面出现状态为Dead的Executor,往往是因为Spark Executor由于某种原因退出了。
如何进入SparkUI页面,详情请参见Spark UI。
常见场景如下。
Driver日志出现如下报错:ERROR TaskSchedulerImpl: Lost executor xx on xx.xx.xx.xx:The executor with id xx exited with exit code 137.
原因:Executor进程内存用超了。容器的整体内存使用超过了容器最大允许使用内存上限,导致Spark进程被kill-9强制杀掉了。Spark Executor除了JVM本身使用内存外,往往还包括堆外内存(Shuffle、Cache),以及Python UDF等使用的内存。
解决方案:调大参数spark.executor.memoryOverhead(单位MB)。该参数表示容器内部非Spark Executor进程可使用的内存容量,默认是Executor容器总内存容量的30%。比如您当前配置的Executor规格是Medium(2C8G),那么默认的MemoryOverhead是2.4G,您可以调大该配置如下:
spark.executor.memoryOverhead = 4000。
2.日志中出现java.lang.OutOfMemoryError的日志。
原因:在SparkUI->Executors页面查看状态为Dead的Executor的stderr/stdout日志链接查找具体报错原因。
解决方案如下。
优化应用,避免大内存占用。
调大Executor资源规格,比如Small提高到Medium。
3.除上述报错以外,其他报错的解决方案。
查看Dead状态的Executor日志,如果报错位置位于用户业务代码,需要业务开发解决。其他错误信息您可以在搜索引擎中搜索相关报错信息。
Spark访问数据源网络不通怎么办?
默认情况下,DLA Spark不能访问用户VPC,只能访问OSS、Tablestore、MaxCompute等服务型数据源,并且不能访问公网。
DLA Spark可以通过挂载用户VPC网卡的方式来访问用户VPC中的数据源,以及访问公网。挂载用户网卡后,网络模型与一台普通用户VPC的ECS完全一样,可以复用阿里云VPC网络产品的所有功能,包括内网、公网、专线等等。如何挂载用户网卡,详情请参见文档配置数据源网络。
如何处理Spark作业日志中报错:ClassNotFound?
常见原因:一般是由于缺少类导致。您可以通过打开所上传的JAR包(jar tvf xxx.jar | grep xxxx),确认该类是否存在。
解决方案如下。
如果是用户业务相关的类,需要重新打包,确保目标类被打进去。
如果是第三方包,您可以采用如下方式。
使用Maven的Shade或者Assembly插件,加入依赖包(Shade和Assembly可以自行查找Maven相关资料)。
使用作业配置指南中“jars”参数将第三方JAR包单独上传。
如何处理Spark作业日志中报错:NoSuchMethod?
常见原因:出现了JAR包冲突,可能是引入了跟Spark冲突的第三方包导致。
解决方案:您可以通过Provided、Relocation等Maven常见的冲突解决方式来解决,相关技术属于通用技术,您可以进行搜索或者参考dla spark demo项目进行Maven Pom配置。
为什么Spark SQL作业使用show tables或者show database查询发现显示的列表不足?
首先请确认是否使用了DLA的元数据服务。
如果您使用的是DLA的元数据服务,需要确认权限问题。您只能看到自己具有权限的库表,其他库表隐藏。
如果您使用的不是DLA的元数据服务,需要确认自建元数据服务的权限和连通的正确性。
为什么在DLA SQL中执行select * from db1.table1成功, 但在Spark中报错?
详细报错如下。
java.lang.NullPointerException
at java.net.URI$Parser.parse(URI.java:3042)
at java.net.URI.<init>(URI.java:588)
at org.apache.spark.sql.hive.client.JianghuClientImpl$$anonfun$getTableOption
常见原因如下。
表的存储格式不对,目前只支持OSS和HDFS。
表名中出现了中划线
-
,中划线为Spark SQL保留字,不允许在表名中使用。
为什么在DLA SQL中执行select * from db1.table1有数据,但在Spark中没有?
常见原因如下。
表中对应的OSS或者HDFS地址有嵌套关系。例如您指定的LOCATION为
oss://db/table/
, 指定了partiion1和parition2,则您的数据文件应当类似oss//db/table/partition1=a/partiion2=b/data.csv
。DLA SQL支持多层嵌套目录oss//db/table/partition1=a/partiion2=b/extral_folder/data.csv
,但Spark SQL暂不支持。DLA SQL的语法和Spark SQL的语法略有区别,如何调试SQL,请参见Spark SQL。
为什么Spark作业提示错误日志oss object 403?
常见原因如下。
DLA Spark不支持跨Region读JAR包或者读文件。
通过参数spark.dla.rolearn指定的Role没有读取这个OSS路径的权限。
文件地址填写错误。
文件与文件之间没有用逗号隔开或者写成JSON的List。
如何处理Spark SQL读JSON外表(包含日志投递自建)时的报错ClassNotFoundException: org.apache.hadoop.hive.serde2.JsonSerDe?
解决方案具体步骤如下。
下载https://repo1.maven.org/maven2/org/apache/hive/hive-serde/3.1.2/hive-serde-3.1.2.jar上传至OSS。
在Spark SQL开头添加语句
add jar oss://path/to/hive-serde-3.1.2.jar;
。
如何处理执行Spark SQL报错:Exception in thread "main" java.io.IOException: No FileSystem for scheme: oss?
解决方案:您可以在Spark SQL中添加如下命令。
set spark.dla.connectors=oss;
作业慢如何排查?
常见的作业执行慢可以分为两大类:
作业异常导致,您可以通过下面方法1和方法2排查。
作业无异常仍然很慢,您可以通过方法3、方法4和方法5排查。
1. 查看是否有Executor状态是Dead。
查看方式:单击展开对应作业的操作列表,点击SparkUI进入Spark页面,切换到Executors页面,查看Status字段。
解决方案:具体解决办法请参见Spark Executor出现Dead怎么处理。
2. 查看Driver日志,是否有异常信息导致Task终止并重试。
查看方式:单击展开对应作业的操作列表,点击SparkUI进入Spark页面,切换到Executors页面,找到Executor ID字段中为driver的stderr日志。
解决方案:通过报错信息查看异常的具体原因,大部分跟业务逻辑相关,您可以对其进行排查或者通过搜索引擎搜索解决。
如果是OOM异常则需要检查业务逻辑是否有大内存占用,特别是某个字段特别大的情况,如果确实需要更大内存,您可以考虑使用更大规格的Executor或Driver节点。
3. 查看是否由资源不足导致。
查看方法:单击展开对应作业的操作列表,点击SparkUI进入Spark页面,切换到Stages页面,从Stage列表中,找到执行比较慢的一些Stage,查看这些Stage的并发度(Tasks: Succeeded/Total)。
如果Stage的Total比(Executor数目)*(Executor cores)多,那么就确认存在资源不足。
比如某个Stage Tasks Total是100,spark.executor.instances=5,spark.executor.resourceSpec=medium(2C8G),那么每一轮Tasks只能跑10个,需要跑10轮。
此时需要增加作业的资源总量,调大spark.executor.instances参数,或者调大Executor规格(spark.executor.resourceSpec)。最好不要超过同时运行的Stage的Tasks总数,否则会导致资源浪费。
4. 查看是否由GC导致。
查看方式:单击展开对应作业的操作列表,点击SparkUI进入Spark页面,切换到Executors页面,查看Task Time (GC Time)字段。
如果某些Executor GC Time比较多时,您可以采取如下解决方案。
优化逻辑。
增大Executor或Driver的节点规格。
5. 查看Driver或Executor堆栈慢在哪里。
查看方式:单击展开对应作业的操作列表,点击SparkUI进入Spark页面,切换到Executors页面,查看Thread Dump字段。
堆栈只有在作业running状态才能查看。
解决方案:多次刷新堆栈查看作业运行卡在什么地方。
如果集中卡在某一个或者某几个函数调用上,那么说明该部分逻辑有热点或者实现效率比较低,您可以考虑优化该部分逻辑。
如果卡在Spark的某些调用中,您可以通过搜索引擎搜索解决。