前提条件:前一段时间应用的海豚为了支持一些新特性做了版本升级,从3.0.0的版本升级到到了3.1.6版本,使用hive的UDF自定义函数碰到了一些问题,现记录如下:
1、使用UDF函数后会导致运行时报空指针异常
经过一系列排查发现是在master节点生成工作流实例时初始化获取字段为空,涉及到BaseTaskProcessor和HadoopUtils类(涉及到海豚源码结构及运行逻辑后续会专门整理篇幅说明),话不多说,上对应位置代码。
海豚初始化工作流实例的udf函数代码如下:
private void setTaskUdfFuncResourceInfo(Map<Integer, AbstractResourceParameters> map) {
if (MapUtils.isEmpty(map)) {
return;
}
List<UdfFunc> udfFuncList = processService.queryUdfFunListByIds(map.keySet().toArray(new Integer[map.size()]));
udfFuncList.forEach(udfFunc -> {
UdfFuncParameters udfFuncParameters = JSONUtils.parseObject(JSONUtils.toJsonString(udfFunc), UdfFuncParameters.class);
udfFuncParameters.setDefaultFS(HadoopUtils.getInstance().getDefaultFS());
String tenantCode = processService.queryTenantCodeByResName(udfFunc.getResourceName(), ResourceType.UDF);
udfFuncParameters.setTenantCode(tenantCode);
map.put(udfFunc.getId(), udfFuncParameters);
});
}
在运行过程中HadoopUtils.getInstance().getDefaultFS()会返回为空导致再SqlTask执行逻辑中创建UDF函数会抛出空指针异常,可以观察一下两个版本的defaultFS的初始化逻辑:
3.0.0-HadoopUtils
String defaultFS = configuration.get(Constants.FS_DEFAULT_FS);
if (StringUtils.isBlank(defaultFS)){
defaultFS= PropertyUtils.getString(Constants.FS_DEFAULT_FS);
}
//first get key from core-site.xml hdfs-site.xml ,if null ,then try to get from properties file
// the default is the local file system
if (StringUtils.isNotBlank(defaultFS)) {
Map<String, String> fsRelatedProps = PropertyUtils.getPrefixedProperties("fs.");
configuration.set(Constants.FS_DEFAULT_FS, defaultFS);
fsRelatedProps.forEach((key, value) -> configuration.set(key, value));
} else {
logger.error("property:{} can not to be empty, please set!", Constants.FS_DEFAULT_FS);
throw new NullPointerException(
String.format("property: %s can not to be empty, please set!", Constants.FS_DEFAULT_FS)
);
}
3.1.6-HadoopUtils
String defaultFS = configuration.get(Constants.FS_DEFAULT_FS);
if (StringUtils.isBlank(defaultFS)) {
defaultFS = PropertyUtils.getString(Constants.FS_DEFAULT_FS);
}
// first get key from core-site.xml hdfs-site.xml ,if null ,then try to get from properties file
// the default is the local file system
if (StringUtils.isNotBlank(defaultFS)) {
Map<String, String> fsRelatedProps = PropertyUtils.getPrefixedProperties("fs.");
configuration.set(Constants.HDFS_DEFAULT_FS, defaultFS);
fsRelatedProps.forEach((key, value) -> configuration.set(key, value));
} else {
logger.error("property:{} can not to be empty, please set!", Constants.FS_DEFAULT_FS);
throw new NullPointerException(
String.format("property: %s can not to be empty, please set!", Constants.FS_DEFAULT_FS));
}
对应获取的方法为:
/**
* @return DefaultFS
*/
public String getDefaultFS() {
return getConfiguration().get(Constants.FS_DEFAULT_FS);
}
3.1.6版本set的key值由Constants.FS_DEFAULT_FS变为了Constants.HDFS_DEFAULT_FS,就会导致获取defaultFS为空,3.2.0版本给出了解决方案,代码如下:
/**
* @return DefaultFS
*/
public String getDefaultFS() {
String defaultFS = PropertyUtils.getString(Constants.FS_DEFAULT_FS);
if(StringUtils.isBlank(defaultFS)){
defaultFS = getConfiguration().get(Constants.HDFS_DEFAULT_FS);
}
return defaultFS;
}
可以通过修改代码重新打包代码替换master项目中的对应jar包可以解决此问题
2、使用kerbros认证后提交hiveSQL运行失败,提示kerbros认证不通过
这个问题是属于配置问题了,开启kerbros认证后我们直接执行sql加上kerbros认证可以执行,加上UDF函数后提示认证不通过,初次排查是因为执行引擎我们集群默认使用的是tez,修改为mr之后就可以执行,再进一步排查是海豚配置文件中的resource.hdfs.fs.defaultFS没有配置为大数据集群的域名导致,配置完重启后,完美解决!