OOM问题
如果一个UDF函数内部包含一个几百兆的资源文件。如果UDF入口类和资源文件在一个jar包中时。 会随着并行度,这些资源会被复制多份。 从而导致OOM异常。
解决方案
一:提高JVM堆内存
提高JAVA_OPT Xmx参数, 所有BE的be.conf。
二:将资源jar包和UDF入口类包分开
思路: 将资源包单独部署, 用其他轻量级的包引用这个资源包。 可以实现资源包在运行时只占用一份内存资源,多个并行度到处引用的效果。
1:先打包文件资源所在的包。此步略......
2:将资源所在包放入{DORIS_HOME}/ be/lib/java_extensions/java-udf文件夹中, 可在BE启动时加载资源文件。
3:创建一个udf入口文件。
import cn.yto.ipplus360.model.Ipv4Basic;
import cn.yto.ipplus360.utils.IpUtils;
public class IpToAddressUDF {
public String evaluate(String arg) {
// 代码逻辑
// 此处是调用资源文件的核心步骤。
Ipv4Basic basic = IpUtils.getBasic(ip);
//代码逻辑
}
}
4: 编译
-- 将java文件编辑成class文件,同时指定要引用的类路径(即资源所在包.jar)
javac -cp {DORIS_HOME}/ be/lib/java_extensions/java-udf/资源所在包.jar 上一步的java文件.java
-- 第一步生成的class文件把他打成jar包。
jar -cvf udf.jar udf.class
-- 生成的java包可作为创建udf函数的入口文件。
5: 创建udf函数
CREATE FUNCTION ipudf(string) RETURNS string PROPERTIES (
"SYMBOL"="入口类名", -- 因为只有一个java文件, 没有包路径。
"file"="file:/任一文件路径/udf.jar",
"ALWAYS_NULLABLE"="false",
"TYPE"="JAVA_UDF"
);
至此, 该UDF函数创建成功, 且经过测试, 在大数据量下稳定运行。 不会造成OOM。