本文为您介绍使用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);