本文為您介紹使用Spark過程中的常見問題。
問題類別 | 常見問題 |
開發Spark | |
作業報錯 |
如何自檢項目工程?
建議您檢查如下內容:
檢查pom.xml。
<dependency> <groupId>org.apache.spark</groupId> <artifactId>spark-core_${scala.binary.version}</artifactId> <version>${spark.version}</version> <scope>provided</scope> // spark-xxxx_${scala.binary.version} 依賴scope必須是provided。 </dependency>
檢查主類spark.master。
val spark = SparkSession .builder() .appName("SparkPi") .config("spark.master", "local[4]") // 如果是以yarn-cluster方式提交,代碼中如果有local[N]的配置,將會報錯。 .getOrCreate()
檢查主類Scala代碼。
object SparkPi { // 必須是object,如果在IDEA創建文件的時候寫為class,main函數是無法加載的。 def main(args: Array[String]) { val spark = SparkSession .builder() .appName("SparkPi") .getOrCreate()
檢查主類代碼配置。
val spark = SparkSession .builder() .appName("SparkPi") .config("key1", "value1") .config("key2", "value2") .config("key3", "value3") ... // 如果執行local測試時,將MaxCompute配置在hard-code代碼里,部分配置是無法生效的。 .getOrCreate()
說明建議您在使用yarn-cluster方式提交任務時,將配置項都寫在spark-defaults.conf中。
在DataWorks上運行ODPS Spark節點的步驟是什么?
在本地Python環境中編輯Spark代碼并打包。本地Python環境版本要求為Python 2.7。
上傳資源包至DataWorks。詳情請參見創建并使用MaxCompute資源。
在DataWorks上創建ODPS Spark節點。詳情請參見創建ODPS Spark節點。
編寫代碼并運行節點,在DataWorks控制臺上即可查看運行結果。
Spark on MaxCompute如何在本地進行調試?
您可以通過IntelliJ IDEA在本地進行調試。詳情請參見搭建Linux開發環境。
如何通過Spark訪問VPC環境內的服務?
更多通過Spark訪問VPC環境內的服務信息,請參見Spark訪問VPC實例。
如何把JAR包當成資源來引用?
您可以通過參數spark.hadoop.odps.cupid.resources
指定需要引用的資源。資源可以多個項目共享,建議您設置相關權限確保數據安全。示例如下。
spark.hadoop.odps.cupid.resources = projectname.xx0.jar,projectname.xx1.jar
如何通過Spark傳入參數?
傳參詳情請參見Spark on DataWorks。
如何將Spark流式讀取的DataHub數據寫入MaxCompute?
示例代碼請參見DataHub。
如何將開源Spark代碼遷移至Spark on MaxCompute?
您可以根據作業場景選擇的遷移方案如下:
作業無需訪問MaxCompute表和OSS。
您可以直接運行已有JAR包,詳情請參見搭建Linux開發環境。對于Spark或Hadoop的依賴必須設置為provided。
作業需要訪問MaxCompute表。
配置相關依賴后重新打包即可,詳情請參見搭建Linux開發環境。
訪問OSS所需要的包,打通網絡請參見Spark訪問VPC實例。
配置相關依賴后重新打包即可,詳情請參見搭建Linux開發環境。
如何通過Spark處理MaxCompute中的表數據?
Spark on MaxCompute支持Local、Cluster和DataWorks運行模式。三種模式的配置不同,詳情請參見運行模式。
如何設置Spark資源并行度?
Spark 資源并行度由Executor數量和Executor CPU核數共同決定,任務可并行執行的最大Task數量為Executor數量 * Executor CPU核數
。
Executor數量
參數:
spark.executor.instances
。參數說明:該參數用于設置作業申請的Executor數量。
Executor CPU核數
參數:
spark.executor.cores
。參數說明:該參數用于設置每個Executor進程的CPU核數,決定每個Executor進程并行執行Task的能力,每個CPU核同一時間只能執行一個Task。通常Executor的CPU核數設置為
2~4
較為合適。
如何解決內存不足問題?
常見報錯:
java.lang.OutOfMemoryError: Java heap space
。java.lang.OutOfMemoryError: GC overhead limit exceeded
。Cannot allocate memory
。The job has been killed by "OOM Killer", please check your job's memory usage
。
解決方案:
設置Executor內存。
參數:
spark.executor.memory
。參數說明:代表每個Executor的內存。通常與
spark.executor.cores
保持1:4
設置即可,例如設置spark.executor.cores
為1
,spark.executor.memory
為4 GB
。當Executor拋出java.lang.OutOfMemoryError
異常時,需要調大該值。
設置Executor堆外內存。
參數:
spark.executor.memoryOverhead
。參數說明:代表每個Executor的額外內存,主要用于JVM自身、字符串、NIO Buffer等開銷。默認大小為
spark.executor.memory * 0.1
,最小384 MB。通常不需要額外設置,當Executor日志出現Cannot allocate memory
或OOM Killer報錯時,需要調大該值。
設置Driver內存。
參數:
spark.driver.memory
。參數說明:代表Driver的內存大小。通常與
spark.driver.cores
保持1:4
設置即可。當Driver需要Collect較大數據量,或拋出java.lang.OutOfMemoryError
異常時,需要調大該值。
設置Driver堆外內存。
參數:
spark.driver.memoryOverhead
。參數說明:代表Driver的額外內存。默認為大小
spark.driver.memory * 0.1
,最小384 MB。當Driver日志出現Cannot allocate memory
報錯,需要調大該值。
如何解決磁盤不足問題?
問題現象
出現報錯:
No space left on device
。問題原因:該錯誤意味著本地磁盤不足,通常該報錯會在Executor中出現,并導致Executor退出。
解決方案:
增加磁盤大小
參數:
spark.hadoop.odps.cupid.disk.driver.device_size
。默認值:20 GB。
參數說明:默認Driver和Executor各提供20GB的本地磁盤,當磁盤空間不足時可以適當調大該參數。注意該參數必須要配置在
spark-defaults.conf
或DataWorks的配置項中才會生效。
增加Executor數量
如果您調整本地磁盤大小到100GB以后,仍然報該錯誤,說明單個Executor Shuffle數據已經超過上限,可能是遇到了數據傾斜,這種情況下對數據重分區會有幫助。也可能確實是數據量太大,那就需要調整
spark.executor.instances
參數,增加Executor的數量。
如何引用MaxCompute Project中的資源?
當前Spark on MaxCompute支持以下兩種方式來訪問MaxCompute中的資源:
通過參數配置直接引用MaxCompute資源。
參數:
spark.hadoop.odps.cupid.resources
。參數格式:
<projectname>.<resourcename>[:<newresourcename>]
。參數說明:該配置項指定了任務運行所需要的MaxCompute資源,詳情請參見資源操作。指定的資源將被下載到Driver和Executor的當前工作目錄。同一個任務可引用多個資源,資源之間用逗號分隔。資源下載到工作目錄后默認名字是
<projectname>.<resourcename>
,在配置時通過<projectname>.<resourcename>:<newresourcename>
進行重命名。需要注意該配置項必須要配置在spark-default.conf
中或DataWorks的配置項中才能生效。示例:
## 以下配置必須在DataWorks配置項/spark-defaults.conf文件中添加 ## 同時引用多個資源:同時引用public.python-python-2.7-ucs4.zip和public.myjar.jar spark.hadoop.odps.cupid.resources=public.python-python-2.7-ucs4.zip,public.myjar.jar ## 重命名示例:引用并將public.myjar.jar重命名為myjar.jar spark.hadoop.odps.cupid.resources=public.myjar.jar:myjar.jar
在DataWorks中引用資源。
將MaxCompute中的資源添加至DataWorks數據開發面板的業務流程中,詳情請參見MaxCompute資源管理。
在DataWorks ODPS Spark節點中選擇jar、file、archive資源。
說明該方案在任務運行時會上傳資源,對于較大資源建議采用方案一進行引用。
如何訪問VPC?
當前Spark on MaxCompute支持以下兩種方式來訪問阿里云VPC中的服務:
反向訪問方式
使用限制
只能訪問與MaxCompute相同Region的阿里云VPC。
使用流程:
在要訪問的服務中添加IP白名單,允許
100.104.0.0/16
網段的訪問。作業配置
spark.hadoop.odps.cupid.vpc.domain.list
參數。該配置描述了需要訪問的一個或多個實例的網絡情況。配置值為JSON格式,需要把JSON壓縮成一行。示例如下,您需要將RegionID、VPCID、實例域名、端口等替換為實際值即可。
## 以下配置必須在DataWorks配置項/spark-defaults.conf文件中添加 spark.hadoop.odps.cupid.vpc.domain.list={"regionId":"cn-beijing","vpcs":[{"vpcId":"vpc-2zeaeq21mb1dmkqh*****","zones":[{"urls":[{"domain":"dds-2ze3230cfea0*****.mongodb.rds.aliyuncs.com","port":3717},{"domain":"dds-2ze3230cfea0*****.mongodb.rds.aliyuncs.com","port":3717}]}]}]}
通過ENI專線訪問
使用限制
通過ENI專線可以打通一個相同Region的VPC,如果您的作業需要同時訪問多個VPC,則可以將已經通過ENI專線打通的VPC與其他VPC之間再做打通即可。
使用流程:
自助開通ENI專線,詳情請參見Spark訪問VPC實例。
在要訪問的服務中添加白名單,授權代表MaxCompute的安全組(即上一步中提供的安全組)能訪問的具體端口。
例如需要訪問阿里云RDS,則需要在RDS中增加規則,允許第1步中創建的安全組訪問。如果用戶需要訪問的服務無法添加安全組,只能添加IP,那么需要將第一步中所使用的vSwitch網段都添加進來。
作業配置
spark.hadoop.odps.cupid.eni.info
和spark.hadoop.odps.cupid.eni.enable
參數。使用示例如下,需要把RegionID和VPCID替換為實際值。
## 以下配置必須在DataWorks配置項/spark-defaults.conf文件中添加 spark.hadoop.odps.cupid.eni.enable = true spark.hadoop.odps.cupid.eni.info = [regionid]:[vpcid]
如何訪問公網?
當前Spark on MaxCompute支持以下兩種方式來訪問公網服務:
通過SmartNAT訪問
假設需要訪問
https://aliyundoc.com:443
,流程如下。您可以通過申請鏈接或搜索(釘釘群號:11782920)加入MaxCompute開發者社區釘群聯系MaxCompute技術支持團隊將
https://aliyundoc.com:443
加入到odps.security.outbound.internetlist
中。使用如下命令示例配置Spark作業級別的公網訪問白名單以及SmartNAT開關。
## 以下配置必須在DataWorks配置項/spark-defaults.conf文件中添加 spark.hadoop.odps.cupid.internet.access.list=aliyundoc.com:443 spark.hadoop.odps.cupid.smartnat.enable=true
通過ENI專線訪問
自助開通ENI專線,詳情請參見Spark訪問VPC實例。
確保專線VPC有訪問公網的能力,詳情請參見使用公網NAT網關SNAT功能訪問互聯網。
使用如下命令示例配置Spark作業級別的公網訪問白名單以及ENI開關,需要把RegionID和VPCID替換為實際值。
## 以下配置必須在DataWorks配置項/spark-defaults.conf文件中添加 spark.hadoop.odps.cupid.internet.access.list=aliyundoc.com:443 spark.hadoop.odps.cupid.eni.enable=true spark.hadoop.odps.cupid.eni.info=[region]:[vpcid]
如何訪問OSS?
當前Spark on MaxCompute支持使用Jindo SDK來訪問阿里云OSS,需要配置以下信息:
配置Jindo SDK及OSS Endpoint。
命令示例如下。
## 引用JindoSDK Jar。以下配置必須在DataWorks配置項/spark-defaults.conf文件中添加 spark.hadoop.odps.cupid.resources=public.jindofs-sdk-3.7.2.jar ## 設置OSS實現類。 spark.hadoop.fs.AbstractFileSystem.oss.impl=com.aliyun.emr.fs.oss.OSS spark.hadoop.fs.oss.impl=com.aliyun.emr.fs.oss.JindoOssFileSystem ## 設置OSS Endpoint spark.hadoop.fs.oss.endpoint=oss-[YourRegionId]-internal.aliyuncs.com ## 通常無需設置OSS endpoint網絡白名單,若作業運行過程中發現網絡不通,可以需要通過以下參數添加白名單。 ## 以下配置必須在DataWorks配置項/spark-defaults.conf文件中添加 spark.hadoop.odps.cupid.trusted.services.access.list=[YourBucketName].oss-[YourRegionId]-internal.aliyuncs.com
說明在Spark on MaxCompute集群模式運行時只支持OSS內網Endpoint,不支持外網Endpoint。OSS Region和Endpoint映射請參見OSS地域和訪問域名。
配置OSS鑒權信息,當前Jindo SDK支持以下兩種方式鑒權。
使用AccessKey鑒權,配置示例如下:
val conf = new SparkConf() .setAppName("jindo-sdk-demo") # 配置access-key鑒權參數 .set("spark.hadoop.fs.oss.accessKeyId", "<YourAccessKeyId") .set("spark.hadoop.fs.oss.accessKeySecret", "<YourAccessKeySecret>")
使用STS Token鑒權,使用流程如下:
單擊一鍵授權,將當前云賬號的OSS資源通過StsToken的方式授權給MaxCompute項目直接訪問。
說明當MaxCompute的ProjectOwner為OSS云賬號時,才可以執行一鍵授權。
配置開啟本地HTTP服務。
命令示例如下。
## 以下配置必須在DataWorks配置項/spark-defaults.conf文件中添加 spark.hadoop.odps.cupid.http.server.enable = true
配置鑒權信息。
命令示例如下。
val conf = new SparkConf() .setAppName("jindo-sdk-demo") # 配置云服務角色鑒權 # ${aliyun-uid}是阿里云用戶UID # ${role-name}是角色名稱 .set("spark.hadoop.fs.jfs.cache.oss.credentials.provider", "com.aliyun.emr.fs.auth.CustomCredentialsProvider") .set("spark.hadoop.aliyun.oss.provider.url", "http://localhost:10011/sts-token-info?user_id=${aliyun-uid}&role=${role-name}")
如何引用Python三方庫?
問題現象:PySpark作業運行時拋出
No module named 'xxx'
異常。問題原因:PySpark作業依賴Python第三方庫,在當前MaxCompute平臺默認的Python環境中尚未安裝。
解決方案:您可以采用以下幾種方案添加第三方庫依賴。
直接使用MaxCompute Python公共環境。
您只需要在DataWorks配置項或
spark-defaults.conf
文件中添加以下配置即可,不同Python版本配置如下:Python 2配置
## Python 2.7.13 配置 ## 以下配置必須在DataWorks配置項/spark-defaults.conf文件中添加 spark.hadoop.odps.cupid.resources = public.python-2.7.13-ucs4.tar.gz spark.pyspark.python = ./public.python-2.7.13-ucs4.tar.gz/python-2.7.13-ucs4/bin/python ## 三方庫列表 https://odps-repo.oss-cn-hangzhou.aliyuncs.com/pyspark/py27/py27-default_req.txt.txt
Python 3配置
## Python 3.7.9 配置 ## 以下配置必須在DataWorks配置項/spark-defaults.conf文件中添加 spark.hadoop.odps.cupid.resources = public.python-3.7.9-ucs4.tar.gz spark.pyspark.python = ./public.python-3.7.9-ucs4.tar.gz/python-3.7.9-ucs4/bin/python3 ## 三方庫列表 https://odps-repo.oss-cn-hangzhou.aliyuncs.com/pyspark/py37/py37-default_req.txt
上傳單個WHEEL包。
該方案適用于Python三方依賴數量較少、較為簡單的情況,命令示例如下。
##需要將wheel包重命名為zip包,例如將pymysql的wheel包重命名為pymysql.zip ##將重命名后的zip包上傳(文件類型為archive) ##在Dataworks spark節點引用該zip包(archive類型) ##在spark-defaults.conf或dataworks配置項中添加配置以下后即可import ## 配置 spark.executorEnv.PYTHONPATH=pymysql spark.yarn.appMasterEnv.PYTHONPATH=pymysql ## 上傳代碼 import pymysql
上傳完整自定義Python環境。
適用于依賴較為復雜或需要自定義Python版本的情況。您需利用Docker容器打包并上傳完整Python環境,詳情請參見Package依賴。
如何解決Jar依賴沖突問題?
問題現象:運行時拋出
NoClassDefFoundError或NoSuchMethodError
異常。問題原因:通常是由于Jar包中的第三方依賴與Spark依賴版本沖突,需要檢查上傳的主Jar包及第三方依賴庫,排除沖突的依賴。
解決方案:
Pom自檢。
將Spark社區版依賴設置為Provided。
將Hadoop社區版依賴設置為Provided。
將Odps/Cupid依賴設置為Provided。
排除沖突的依賴。
使用
maven-shade-plugin relocation
解決包沖突。
如何使用Local模式進行調試?
Spark 2.3.0
在spark-defaults.conf中添加以下配置。
spark.hadoop.odps.project.name =<Yourprojectname> spark.hadoop.odps.access.id =<YourAccessKeyID> spark.hadoop.odps.access.key =<YourAccessKeySecret> spark.hadoop.odps.end.point =<endpoint>
使用Local模式運行任務。
./bin/spark-submit --master local spark_sql.py
Spark 2.4.5/Spark 3.1.1
創建
odps.conf
文件,并在文件中添加以下配置。odps.access.id=<YourAccessKeyID> odps.access.key=<YourAccessKeySecret> odps.end.point=<endpoint> odps.project.name=<Yourprojectname>
添加環境變量指向
odps.conf
文件位置。export ODPS_CONF_FILE=/path/to/odps.conf
使用Local模式運行任務。
./bin/spark-submit --master local spark_sql.py
常見報錯
報錯1:
報錯信息:
Incomplete config, no accessId or accessKey
。Incomplete config, no odps.service.endpoint
。
報錯原因:在Local模式開啟了EventLog。
解決方案:將
spark-defaults.conf
中的spark.eventLog.enabled=true
參數刪除即可。
報錯2:
報錯信息:
Cannot create CupidSession with empty CupidConf
。報錯原因:Spark 2.4.5或Spark 3.1.1 無法讀取
odps.access.id
等信息。解決方案:創建
odps.conf
文件,并添加環境變量后再運行任務
報錯3:
報錯信息:
java.util.NoSuchElementException: odps.access.id
。報錯原因:Spark 2.3.0 無法讀取
odps.access.id
等信息。解決方案:在
spark-defaults.conf
中添加spark.hadoop.odps.access.id
等配置信息。
運行Spark作業時,報錯User signature does not match,如何解決?
問題現象
運行Spark作業時,返回報錯如下。
Stack: com.aliyun.odps.OdpsException: ODPS-0410042: Invalid signature value - User signature does not match
產生原因
身份驗證未通過,AccessKey ID或AccessKey Secret有誤。
解決措施
請檢查spark-defaults.conf提供的AccessKey ID、AccessKey Secret和阿里云官網控制臺用戶信息管理中的AccessKey ID、AccessKey Secret是否一致,如果不一致,請修改一致。
運行Spark作業時,報錯You have NO privilege,如何解決?
問題現象
運行Spark作業時,返回報錯如下。
Stack: com.aliyun.odps.OdpsException: ODPS-0420095: Access Denied - Authorization Failed [4019], You have NO privilege 'odps:CreateResource' on {acs:odps:*:projects/*}
產生原因
權限不足,需要申請權限。
解決措施
需要由項目所有者授予Resource的Read和Create權限。更多授權信息,請參見MaxCompute權限。
運行Spark作業時,報錯Access Denied,如何解決?
問題現象
運行Spark作業時,返回報錯如下。
Exception in thread "main" org.apache.hadoop.yarn.exceptions.YarnException: com.aliyun.odps.OdpsException: ODPS-0420095: Access Denied - The task is not in release range: CUPID
產生原因
原因一:Spark-defaults.conf中配置的AccessKey ID、AccessKey Secret不正確。
原因二:項目所在的地域未提供Spark on MaxCompute服務。
解決措施
原因一的解決措施:檢查Spark-defaults.conf配置信息,修改為正確的AccessKey ID、AccessKey Secret。更多信息,請參見搭建Linux開發環境。
原因二的解決措施:確認項目所在的地域是否已經提供了Spark on MaxCompute服務或加入釘釘群21969532(Spark on MaxCompute支持群)咨詢。
運行Spark作業時,報錯No space left on device,如何解決?
Spark使用網盤進行本地存儲。Shuffle數據和BlockManager溢出的數據均存儲在網盤上。網盤的大小通過spark.hadoop.odps.cupid.disk.driver.device_size參數控制,默認為20 GB,最大為100 GB。如果調整到100 GB仍然報此錯誤,需要分析具體原因。常見原因為數據傾斜,在Shuffle或者Cache過程中數據集中分布在某些Block。此時可以縮小單個Executor的核數(spark.executor.cores),增加Executor的數量(spark.executor.instances)。
運行Spark作業時,報錯Table or view not found,如何解決?
問題現象
運行Spark作業時,返回報錯如下。
Table or view not found:xxx
產生原因
原因一:表或視圖不存在。
原因二:打開了Hive的catalog配置。
解決措施
原因一的解決措施:請創建表。
原因二的解決措施:去掉catalog配置。報錯示例如下,需要去掉
enableHiveSupport()
。spark = SparkSession.builder.appName(app_name).enableHiveSupport().getOrCreate()
運行Spark作業時,報錯Shutdown hook called before final status was reported,如何解決?
問題現象
運行Spark作業時,返回報錯如下。
App Status: SUCCEEDED, diagnostics: Shutdown hook called before final status was reported.
產生原因
提交到集群的user main并沒有通過AM(ApplicationMaster)申請集群資源。例如,用戶沒有新建SparkContext或用戶在代碼中設置spark.master為local。
運行Spark作業時,發生JAR包版本沖突類錯誤,如何解決?
問題現象
運行Spark作業時,返回報錯如下。
User class threw exception: java.lang.NoSuchMethodError
產生原因
JAR包版本沖突或類錯誤。
解決措施
在$SPARK_HOME/jars路徑下找出異常類所在的JAR。
執行如下命令定位第三方庫的坐標以及版本。
grep <異常類類名> $SPARK_HOME/jars/*.jar
在Spark作業根目錄下,執行如下命令查看整個工程的所有依賴。
mvn dependency:tree
找到對應的依賴后,執行如下命令排除沖突包。
maven dependency exclusions
重新編譯并提交代碼。
運行Spark作業時,報錯ClassNotFound,如何解決?
問題現象
運行Spark作業時,返回報錯如下。
java.lang.ClassNotFoundException: xxxx.xxx.xxxxx
產生原因
類不存在或依賴配置錯誤。
解決措施
執行如下命令查看您提交的JAR包中是否存在該類定義。
jar -tf <作業JAR包> | grep <類名稱>
檢查pom.xml文件中的依賴是否正確。
使用Shade方式提交JAR包。
運行Spark作業時,報錯The task is not in release range,如何解決?
問題現象
運行Spark作業時,返回報錯如下。
The task is not in release range: CUPID
產生原因
項目所在地域未開通Spark on MaxCompute服務。
解決措施
請您選擇已經開啟Spark on MaxCompute服務的地域使用。
運行Spark作業時,報錯java.io.UTFDataFormatException,如何解決?
問題現象
運行Spark作業時,返回報錯如下。
java.io.UTFDataFormatException: encoded string too long: 2818545 bytes
解決措施
調整spark-defaults.conf中spark.hadoop.odps.cupid.disk.driver.device_size參數的值。默認為20 GB,最大支持100 GB。
運行Spark作業時,打印的中文亂碼,如何解決?
您需要添加如下配置。
"--conf" "spark.executor.extraJavaOptions=-Dfile.encoding=UTF-8 -Dsun.jnu.encoding=UTF-8"
"--conf" "spark.driver.extraJavaOptions=-Dfile.encoding=UTF-8 -Dsun.jnu.encoding=UTF-8"
Spark調用外網第三方任務時報錯,如何解決?
Spark不能調用外網第三方任務,網絡不通。
您可以在VPC中搭建Nginx反向代理,通過代理訪問外網。Spark支持直接訪問VPC,詳情請參見Spark訪問VPC實例。