栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 前沿技术 > 大数据 > 大数据系统

HiveServer2 用户自定义函数加载本地库出现 UnsatisfiedLinkError 的解决方案

HiveServer2 用户自定义函数加载本地库出现 UnsatisfiedLinkError 的解决方案

创建项目 hive-func,创建函数 CPlusUtil 实现两个整数的加法运算。代码如下:

CPlusUtil.java
package com.baidu.hive.func;

import org.apache.hadoop.hive.ql.exec.UDF;

public class CPlus extends UDF {

    public int evaluate(int a, int b) {
        return CPlusUtil.add(a, b);
    }
}

CPlus 调用 CPlusUtil 的静态方法。

CPlusUtil.java

CPlusUtil 的静态方法是 native 的。

package com.baidu.hive.func;

public class CPlusUtil {

    static {
        System.loadLibrary("cplus");
    }

    public static native int add(int a, int b);
}
生成 hive-func-0.1.0.jar

编译项目,生成 target/hive-func-0.1.0.jar 文件。

mvn clean package
生成 so 文件

先生成头文件

cd target/classes/
javah com.baidu.hive.func.CPlusUtil

查看头文件的内容。

com_baidu_hive_func_CPlusUtil.h
#include 


#ifndef _Included_com_baidu_hive_func_CPlusUtil
#define _Included_com_baidu_hive_func_CPlusUtil
#ifdef __cplusplus
extern "C" {
#endif

JNIEXPORT jint JNICALL Java_com_baidu_hive_func_CPlusUtil_add
  (JNIEnv *, jclass, jint, jint);

#ifdef __cplusplus
}
#endif
#endif

我们在和头文件同目录下创建 CPlusUtil.c 文件,内容如下:

CPlusUtil.c
#include         // JNI header provided by JDK
#include       // C Standard IO Header
#include "com_baidu_hive_func_CPlusUtil.h"   // Generated
 

JNIEXPORT jint JNICALL Java_com_baidu_hive_func_CPlusUtil_add
  (JNIEnv *env, jclass thisObj, jint a, jint b) {
   return a+b;
};
用以下命令生成 so 文件
gcc -fPIC -I"$JAVA_HOME/include" -I"$JAVA_HOME/include/linux" -shared -o libcplus.so CPlusUtil.c

注意:java 里加载的是 cplus,生成的文件是 libcplus.so

拷贝文件到 Hadoop 集群
hadoop fs -mkdir -p /apps/hive;
hadoop fs -put hive-func-0.1.0.jar /apps/hive;
hadoop fs -put libcplus.so /apps/hive;
用 beeline 进行第 1 次测试

第一次可以执行。

create function default.cplus as 'com.baidu.hive.func.CPlus' 
using jar 'hdfs://master-e285d25:8020/apps/hive/hive-func-0.1.0.jar',  
file 'hdfs://master-e285d25:8020/apps/hive/libcplus.so';

select default.cplus(1,2);

退出 beeline

!q
用 beeline 进行第 2 次测试
select default.cplus(1,2);

HiveServer 后台抛出异常 UnsatisfiedlinkError

使用 hive-cli 正常

直接执行 hive 命令,可以正常使用函数。

原因分析

为了避免不同 session 之间的 add jar 造成的相互影响,HiveServer 每个 session 使用一个 class loader。使用函数的时候,从 hdfs 下载 jar 包,修改 session 的 class loader 的 uris,让 session 的 class loader 知道从哪里读取文件。第 1 次运行的时候,调用 System.loadLibrary("cplus"); 是正确的。再次打开一个会话,使用了新的 class loader,认为 CPlus 和 CPlusUtil 类没有加载,造成 CPlus 和 CPlusUtil 两个类都重新加载一遍,本次加载执行 System.loadLibrary("cplus"); 失败。

解决方案 1

    把 libcplus.so 拷贝到 ${HADOOP_HOME}/lib/native 目录下

    把 hive-func-0.1.0.jar 拷贝到 ${HIVE_HOME}/lib 目录下

    重启 hive server2

    测试 hiveserver,多次进出 beeline,执行以下语句,都可以正确执行。

select default.cplus(1,2);
    测试分布式任务,可以正确执行。
create table t1 as select default.cplus(c1, c2) from tableName;
解决方案 1 总结
    拷贝文件到 HiveServer 所在的本地文件系统是为了解决 HiveServer 的执行环境问题。使用 HDFS 上的文件是为了解决分布式执行环境的问题。如果 so 文件或者 jar 文件有修改,需要同时更新 HiveServer 的环境和 HDFS 上的文件,重启 HiveServer。
解决方案2

修改 c 代码,在 so 里判断本进程是否已经加载 so 文件,保证 so 文件只加载一次。使用本方案,不需要在 HiveServer 里放 jar 包和 so 文件。以后函数更新仅用更新 HDFS 上的文件,比较方便。

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/745837.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号