本文為您介紹使用Java語言編寫的MaxCompute UDF的常見問題。
類或依賴問題
調用MaxCompute UDF運行代碼時的常見類或依賴問題如下:
問題現象一:運行報錯描述為
ClassNotFoundException
或Some dependencies are missing
。產生原因:
原因一:建立MaxCompute UDF時指定的資源JAR包不正確。
原因二:MaxCompute UDF依賴的資源JAR包未上傳至MaxCompute,例如依賴的第三方包沒有上傳。
原因三:調用MaxCompute UDF運行代碼時,所處的專案不正確。即MaxCompute UDF不在MaxCompute專案中。例如MaxCompute UDF註冊到了開發專案,但卻在生產專案執行叫用作業。
原因四:檔案資源不存在或資源類型不正確。例如PY檔案,資源類型是PY,但MaxCompute UDF代碼中
get_cache_file
需要的類型是FILE。
解決措施:
原因一的解決措施:檢查JAR包的正確性,並確認JAR包中已經包含需要的類,重新打包並上傳至MaxCompute專案。更多打包上傳操作,請參見打包、上傳及註冊。
原因二的解決措施:將MaxCompute UDF依賴的第三方包作為資源上傳至MaxCompute專案,然後在註冊函數時,依賴資源清單中添加此包。更多上傳資源及註冊函數操作,請參見添加資源和註冊函數。
原因三的解決措施:在報錯的專案下通過MaxCompute用戶端執行
list functions;
命令,確保MaxCompute UDF是真實存在的,且MaxCompute UDF的類和依賴的資源正確。原因四的解決措施:通過MaxCompute用戶端執行
desc function <function_name>;
命令,確保Resources列表已覆蓋所有需要的檔案資源。如果資源類型不符,可執行add <file_type> <file_name>;
重新添加資源。
問題現象二:運行報錯描述為
NoClassDefFoundError
、NoSuchMethodError
或錯誤碼為ODPS-0123055
。產生原因:
原因一:使用者上傳的JAR包中包含的第三方庫的版本與MaxCompute內建的第三方庫的版本不一致。
原因二:Java沙箱限制。作業Instance的Stderr中出現
java.security.AccessControlException: access denied ("java.lang.RuntimePermission" "createClassLoader")
詳細資料,表示是沙箱限制。MaxCompute UDF在分布式環境中運行時收到Java沙箱的限制。更多Java沙箱限制資訊,請參見Java沙箱。
解決措施:
原因一的解決措施:使用
maven-shade-plugin
解決版本不一致問題並修改Import路徑,重新打包為JAR包並上傳至MaxCompute專案。更多打包上傳操作,請參見打包、上傳及註冊。原因二的解決措施:請參見Java沙箱限制問題。
Java沙箱限制問題
效能問題
調用MaxCompute UDF運行代碼時的常見效能問題如下:
問題現象一:運行報錯描述為
kInstanceMonitorTimeout
。產生原因:MaxCompute UDF處理時間過長導致逾時。預設情況下UDF處理資料的時間有限制,在處理一批(通常情況下為1024條)記錄時,必須在1800秒內處理完。這個時間限制並不是針對Worker的總已耗用時間,而是處理一小批記錄的時間。通常情況下SQL處理資料的速率超過了萬條/秒,該限制只是為了防止MaxCompute UDF中出現死迴圈,導致長時間佔用CPU資源的情況。
解決措施:
如果實際計算量很大,可以在MaxCompute UDF的實現Java類的方法中調用
ExecutionContext.claimAlive
來重設計時器。重點最佳化MaxCompute UDF代碼邏輯。後續調用MaxCompute UDF時,可同時在Session層級配置如下參數輔助調節MaxCompute UDF運行過程,提升處理速度。
參數
說明
set odps.function.timeout=xxx;
調整UDF運行逾時時間長度。預設值為1800s。可根據實際情況酌情調大。取值範圍為1s~3600s。
set odps.stage.mapper.split.size=xxx;
調整Map Worker的輸入資料量。預設值為256 MB。可根據實際情況酌情調小。
set odps.sql.executionengine.batch.rowcount=xxx;
調整MaxCompute一次處理的資料行數。預設值為1024行。可根據實際情況酌情調小。
問題現象二:運行報錯描述為
errMsg:SigKill(OOM)
或OutOfMemoryError
。產生原因:MaxCompute運行作業主要分為三個階段:Map、Reduce和Join。如果處理的資料量比較大,會導致各個階段的每個Instance處理的時間比較長。
解決措施:
如果是
fuxi
或runtime
相關代碼報錯,您可以通過設定如下資源參數提升處理速度。參數
說明
set odps.stage.mapper.mem=xxx;
調整Map Worker的記憶體大小。預設值為1024 MB。可根據實際情況酌情調大。
set odps.stage.reducer.mem=xxx;
調整Reduce Worker的記憶體大小。預設值為1024 MB。可根據實際情況酌情調大。
set odps.stage.joiner.mem=xxx;
調整Join Worker的記憶體大小。預設值為1024 MB。可根據實際情況酌情調大。
set odps.stage.mapper.split.size=xxx;
調整Map Worker的輸入資料量。預設值為256 MB。可根據實際情況酌情調大。
set odps.stage.reducer.num=xxx;
調整Reduce階段的Worker數量。可根據實際情況酌情調大。
set odps.stage.joiner.num=xxx;
調整Join階段的Worker數量。可根據實際情況酌情調大。
如果是Java代碼本身報錯,可以在調整上述參數的同時,通過
set odps.sql.udf.jvm.memory=xxx;
參數調大Jvm記憶體。
更多參數詳細資料,請參見SET操作。
UDTF相關問題
調用Java UDTF運行代碼時的常見問題如下:
問題現象一:運行報錯描述為
Semantic analysis exception - only a single expression in the SELECT clause is supported with UDTF's
。產生原因:在SELECT語句中調用Java UDTF時,存在Java UDTF與其他列或運算式混用的問題,Java UDTF暫不支援該用法。錯誤樣本如下。
select b.*, 'x', udtffunction_name(v) from table lateral view udtffunction_name(v) b as f1, f2;
解決措施:您可以將Java UDTF與Lateral View配合使用。命令樣本如下。
select b.*, 'x' from table lateral view udtffunction_name(v) b as f1, f2;
問題現象二:運行報錯描述為
Semantic analysis exception - expect 2 aliases but have 0
。產生原因:Java UDTF代碼中沒有指定輸出資料行名。
解決措施:您可以在調用Java UDTF的SELECT語句中通過
as
子句給出列名。命令樣本如下。select udtffunction_name(paramname) as (col1, col2);