1
文档编写目的
Hive在UDF中获取sessionId可以直接使用提供的java API,但是该UDF如果移植到Impala中是无法获取到Impala连接的SessionId的,要想获取Impala的SessionId,需要用C++来编写。
2
实现思路
1. 根据Impala的源码可知可通过UDF参数中的context上下文对象来取得该SessionId,具体调用关系如下:
context->impl()->state()->session_id();
源码参考:
https://github.com/cloudera/Impala/blob/cdh5-2.9.0_5.12.2/be/src/udf/udf.h#L234
https://github.com/cloudera/Impala/blob/cdh5-2.9.0_5.12.2/be/src/runtime/runtime-state.h#L112
但是从源码中方法的注释上我们可以看到,context的impl()方法是不允许在UDA/UDF中使用的:
因此从官方提供的UDF依赖包impala-udf-devel安装后的库中也可以看到,并没有runtime-state.h等编译需要的依赖文件:
上图的五个声明文件是官方提供的UDF依赖。
按照正常的Impala用C++来实现UDF的流程,context->impl()->state()->session_id()将不能编译成功。
2. 因此在编译该UDF文件时,只能通过引入impala的源码和编译源码时需要的依赖来实现。
3
编译流程
1. 安装maven
下载maven:
wget http://mirror.cogentco.com/pub/apache/maven/maven-3/3.6.0/binaries/apache-maven-3.6.0-bin.tar.gz
解压:
tar -zxvf apache-maven-3.6.0-bin.tar.gz
mv apache-maven-3.6.0 /usr/local/
修改/etc/profile添加到环境变量
export MAVEN_HOME=/usr/local/apache-maven-3.6.0
另外,如果有配anaconda的环境变量,暂时注释
验证maven:
2. 升级cmake
下载cmake-3.3.2-1.gf.el7.x86_64.rpm,并制作本地yum源,可到https://pkgs.org下载:
yum -y install cmake-3.3.2-1.gf.el7.x86_64
3. 安装高版本的g++编译器,impala源码中引入了c++11新特性,g++太低将无法编译,此处安装的是7.3.1版本。
sudo yum -y install centos-release-scl
sudo yum -y install devtoolset-7
scl enable devtoolset-7 bash
验证g++:
4. 下载Impala源码
wget https://codeload.github.com/cloudera/Impala/zip/cdh5-trunk
解压到当前目录
unzip Impala-cdh5-trunk.zip
将该目录添加到环境变量IMPALA_HOME
export IMPALA_HOME=/data/Impala-cdh5-trunk
source /etc/profile
5. 安装依赖
yum install -y redhat-lsb.x86_64
yum -y group install "Development Tools"
yum -y install git ant libevent-devel automake libtool flex bison gcc-c++
yum -y install openssl-devel make
yum -y install doxygen.x86_64 glib-devel python-devel bzip2-devel svn libevent-devel krb5-workstation
yum -y install openldap-devel db4-devel python-setuptools python-pip cyrus-sasl* postgresql postgresql-server ant-nodeps lzo-devel lzop
yum -y install boost boost-devel
6. 编译源码
进入impala源码目录
./buildall.sh -notests(该命令将编译整个工程,耗时较长)
或者执行:
./buildall.sh -cmake_only
上述命令执行完毕之后检查以下几点:
be/generated-sources下是否有gen-cpp目录及内部是否有文件:
toolchain下是否已下载thrift,glog,gflags,rapidjson依赖
7. 创建UDF文件
创建文件夹:
mkdir -p /root/impala-udf
mkdir -p /root/impala-udf/include
将源码包内相关包复制到include下
cp -r toolchain/gflags-2.2.0-p1/include/gflags/ /root/impala-udf/include
cp -r toolchain/glog-0.3.4-p3/include/glog/ /root/impala-udf/include
cp -r toolchain/rapidjson-0.11/include/rapidjson/ /root/impala-udf/include
cp -r toolchain/thrift-0.9.0-p11/include/thrift/ /root/impala-udf/include
cp -r be/generated-sources/gen-cpp /root/impala-udf/include
cp -r be/src/* /root/impala-udf/include
编写获取SessionId的C++代码:
编写getSessionId.h
#ifndef SAMPLES_UDF_H
#define SAMPLES_UDF_H
#include <udf/udf.h>
#include <udf/udf-internal.h>
using namespace impala_udf;
StringVal GetSessionId(FunctionContext* context);
#endif
编写getSessionId.cc
从下方的Impala的JAVA源码中可以看到,SessionId存放在TUniqueId对象的两个字段中,取出时需将其转换成16进制字符串:
此处从context中取得TuniqueId对象之后,将其转化成16进制。
#define __STDC_FORMAT_MACROS
#include <stdlib.h>
#include "getSessionId.h"
#include <udf/udf.h>
#include <udf/udf-internal.h>
#include <runtime/runtime-state.h>
#include <string.h>
#include <vector>
#include <stdio.h>
#include <inttypes.h>
#include<iostream>
using namespace std;
namespace impala{
class TUniqueId;
}
using namespace impala_udf;
string DecIntToHexStr(unsigned long long num)
{
string str;
long long Temp = num / 16;
int left = num % 16;
if (Temp > 0)
str += DecIntToHexStr(Temp);
if (left < 10)
str += (left + '0');
else
str += ('A' + left - 10);
return str;
}
StringVal getSessionId(FunctionContext* context) {
impala::TUniqueId id = context->impl()->state()->session_id();
string idhi = DecIntToHexStr(id.hi);
string idlo = DecIntToHexStr(id.lo);
string sessionid = idhi +":"+ idlo;
return *(new StringVal(sessionid.data()));
}
编写CMakeList.txt文件:
cmake_minimum_required(VERSION 3.2.3)
# where to put generated libraries
set(LIBRARY_OUTPUT_PATH "build")
# where to put generated binaries
set(EXECUTABLE_OUTPUT_PATH "build")
find_program(CLANG_EXECUTABLE clang++)
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -g -ggdb")
include_directories("include")
# Function to generate rule to cross compile a source file to an IR module.
# This should be called with the .cc src file and it will generate a
# src-file-ir target that can be built.
# e.g. COMPILE_TO_IR(test.cc) generates the "test-ir" make target.
set(IR_COMPILE_FLAGS "-emit-llvm" "-O3" "-c" "-Iinclude")
function(COMPILE_TO_IR SRC_FILE)
get_filename_component(BASE_NAME ${SRC_FILE} NAME_WE)
set(OUTPUT_FILE "build/${BASE_NAME}.ll")
add_custom_command(
OUTPUT ${OUTPUT_FILE}
COMMAND ${CLANG_EXECUTABLE} ${IR_COMPILE_FLAGS} ${SRC_FILE} -o ${OUTPUT_FILE}
DEPENDS ${SRC_FILE})
add_custom_target(${BASE_NAME}-ir ALL DEPENDS ${OUTPUT_FILE})
endfunction(COMPILE_TO_IR)
# Build the UDA/UDFs into a shared library.
add_library(getSessionId SHARED getSessionId.cc)
# Custom targest to cross compile UDA/UDF to ir
if (CLANG_EXECUTABLE)
COMPILE_TO_IR(getSessionId.cc )
endif(CLANG_EXECUTABLE)
# This is an example of how to use the test harness to help develop UDF and UDAs.
target_link_libraries(getSessionId ImpalaUdf)
8. 编译UDF
cmake .
make
在该目录的build下可看见编译好的文件
4
验证UDF
1. 将libgetSessionId.so上传hdfs的/tmp下:
hdfs dfs -put libgetSessionId.so /tmp
2. 创建UDF并验证
CREATE FUNCTION getSessionId() RETURNS string location '/tmp/libgetSessionId.so' symbol='getSessionId';
查询
select *,getSessionId() from test_table;
从上图中可以看出,在一次查询中获取的sessionId相同。
断开连接后再次连接查询:
可以看到,与上一次连接相比,SessionId已发生改变。
3. 但是impala不同于hive,在cmz中impala的log不能看到impala的Sessionid,因此,不容易验证获取的正确性,但impala的log中有查询的query_id。
此处我们将context->impl()->state()->session_id();改为context->impl()->state()->query_id();重新编译后上传创建getQueryId()。
CREATE FUNCTION getQueryId() RETURNS string location '/tmp/libgetQueryId.so' symbol='getQueryId';
查询:
select *,getQueryId() from test_table;
可看到在两次的查询中query_id不同,符合预期,并且与log日志中的query_id相同:
5
总结
IMPALA的UDF,不论是java还是c++,都不能操作session。当官方提供的UDF API不能够满足需求时,引入IMPALA的源码来编译时可行的。
扫码关注腾讯云开发者
领取腾讯云代金券
Copyright © 2013 - 2025 Tencent Cloud. All Rights Reserved. 腾讯云 版权所有
深圳市腾讯计算机系统有限公司 ICP备案/许可证号:粤B2-20090059 深公网安备号 44030502008569
腾讯云计算(北京)有限责任公司 京ICP证150476号 | 京ICP备11018762号 | 京公网安备号11010802020287
Copyright © 2013 - 2025 Tencent Cloud.
All Rights Reserved. 腾讯云 版权所有