Hiveserver2的代理执行之路_教练_我要踢球的博客-程序员信息网_hive 代理

技术标签: hive  proxy  代理执行  OLAP  大数据  sql  

背景

对于一个数据平台的SQL查询服务,impala提供了优于hive/spark sql等一批sql-on-mr/spark性能的查询引擎,并且得益于impala可以直接共享hive的metastore,可以对用户提供”一套数据,多种引擎”的服务,目前我们计划在数据平台集成hive/spark/impala这几种SQL引擎。众所周知,hive无论是在稳定性还是在成熟度上都要优于后两者,不管是spark还是impala在使用的过程中总是需要对其进行一定的修改支持hive提供的特性,其中有一个对于平台服务最有用的特性——代理执行。

hiveserver2的代理访问可以使得平台端代理任意用户执行SQL操作就像该用户自己执行的操作一样(就像一个普通用户直接使用hive CLI执行操作),本文主要探索hiveserver2是如何使用代理的方式实现支持不同用户完成SQL操作,为修改impala支持对应的操作做铺垫。

HiveServer2的实现

在启动hive server2的时候,我们通常需要一个hive.keytab,这个用户在hadoop上被配置为可代理的用户(具体的配置是在namenode的core-site.xml中添加hadoop.proxyuser.hive.hosts=xxx和hadoop.proxyuser.hive.groups=xxx配置项,以确定hive用户可以对指定host的指定groups的用户执行代理),除了对hiveserver2配置principal和keytab之外,还需要设置hive.server2.enable.doAs参数为true(该配置项默认值就是true),该配置表示对于用户的操作,hiveserver2将以代理的方式访问HDFS和提交MR任务。

好了,以代理的方式配置好了hiveserver2,我们可以看一下利用这个特性能够做到什么。
在本例中,hive.keytab已经被配置了可代理的权限,其他用户全是普通用户。通过beeline连接hiveserver2,beeline作为client会以当前用户的kerberos cache中认证的kerberos用户作为被代理的账号执行,例如当前机器上的用户是nrpt:

>  klist
Ticket cache: FILE:/tmp/krb5cc_50997
Default principal: nrpt/[email protected]

Valid starting    Expires           Service principal
10/02/2017 09:30  11/02/2017 07:30  krbtgt/[email protected]
     renew until 11/02/2017 09:30

然后连接hiveserver2执行查询:

> beeline -u "jdbc:hive2://db-53.photo.163.org:10000/default;principal=hive/[email protected]"
Connecting to jdbc:hive2://db-53.photo.163.org:10000/default;principal=hive/[email protected]
Connected to: Apache Hive (version 1.2.1)
Driver: Hive JDBC (version 1.2.1)
Transaction isolation: TRANSACTION_REPEATABLE_READ
Beeline version 1.2.1 by Apache Hive
0: jdbc:hive2://db-53.photo.163.org:10000/def> select count(1) from foodmart.sales_fact_1997;
+--------+--+
|  _c0   |
+--------+--+
| 86837  |
+--------+--+
1 row selected (37.497 seconds)

连接成功,此时执行SQL查询,这个查询需要提交MR任务,通过hadoop任务管理界面,可以看到该任务的提交用户是nrpt,也就是被代理的用户。

这里写图片描述

除了任务提交,在访问hive的时候还会涉及到大量的HDFS操作,这种操作是否也是以被代理的账号执行的呢,可以通过如下的SQL验证,create as select会新建一个表并且让将查询结果写入该表。

0: jdbc:hive2://db-53.photo.163.org:10000/def> create table test_nrpt as select * from foodmart.sales_fact_1997;
No rows affected (28.992 seconds)

查看HDFS上的文件权限可以看到该表的数据的确是通过被代理用户(nrpt)执行的。

> hadoop fs -ls hdfs://hz-cluster2/user/nrpt/hive-server/test_nrpt
Found 1 items
-rw-r--r--   3 nrpt hdfs    2971680 2017-02-10 10:25 hdfs://hz-cluster2/user/nrpt/hive-server/test_nrpt/000000_0
> hadoop fs -ls hdfs://hz-cluster2/user/nrpt/hive-server/ | grep test_nrpt
drwxr-xr-x   - nrpt hdfs          0 2017-02-10 10:25 hdfs://hz-cluster2/user/nrpt/hive-server/test_nrpt

演示了这么多,为什么说这个特性是特别重要的呢?对于一个数据平台的开发,往往需要支持不同产品的用户执行SQL,而不同的产品通常使用不同的kerberos用户(对于不同用户的数据安全性的保证),利用hive server2的代理特性,就可以使得不同的用户使用同一个hiveserver2并且彼此之间做到数据和权限的隔离。

客户端代理

好了,那既然可以做到这样是不是就完事了,其实不然,一个数据平台的野心不会仅仅局限在提供一个hiveserver2让用户访问,往往维护封装成一个查询窗口(例如猛犸),用户不需要关心hiveserver2在哪里启动。在这种情况就需要平台端来创建到hiveserver2的连接,然后执行用户输入的查询,并且最重要的一点是需要以用户的身份执行该查询!前面我们看到,如果希望以用户A的身份执行查询那么就需要当前kerberos认证的用户是A,难不成平台端要保存全部的用户keytab,然后在执行不同用户操作的时候执行切换?

如果真的要这么笨重拿就没法玩了,既然hive用户可以在hiveserver2代理任意用户执行查询,那么客户端不是也可以通过hive代理任何用户执行SQL吗?我们需要做代理执行的时候执行逻辑是这样子的:

UserGroupInformation ugi = UserGroupInformation.createProxyUser(proxyUser, UserGroupInformation.getLoginUser());
System.out.println("Current kerberos user : " + ugi);
ugi.doAs(new PrivilegedExceptionAction<Void>() {
    public Void run() throws Exception {
        // do something with user proxyUser.
    }
});

在doAs中执行的操作都是以proxyUser用户的身份执行的,通常这里就是提交MR任务,访问HDFS之类的操作,相信hiveserver2的实现肯定使用的也是类似的方式,当然这里有一个前提条件就是getLoginUser()(通常就是kinit认证的用户或者在程序里面执行kerberos的用户)返回的用户必须具有代理权限,如果任意一个普通用户都可以createProxyUser,人人都变成超级账号了。我们把run方法中写入创建hive connection并且执行查询:

public Void run() throws Exception {
    Class.forName("org.apache.hive.jdbc.HiveDriver");
    Connection conn = DriverManager.getConnection(
        "jdbc:hive2://db-53.photo.163.org:10000/default;principal=hive/ [email protected]");
    Statement statement = conn.createStatement();
    statement.execute("select count(1) from foodmart.sales_fact_1997");
    return null;
}

执行发现并没有预想的那么顺利,出现了kerberos认证的错误:

Current kerberos user : nrpt (auth:PROXY) via hive/[email protected] (auth:KERBEROS)
17/02/10 10:56:31 INFO jdbc.Utils: Supplied authorities: db-53.photo.163.org:10000
17/02/10 10:56:31 INFO jdbc.Utils: Resolved authority: db-53.photo.163.org:10000
17/02/10 10:56:31 ERROR transport.TSaslTransport: SASL negotiation failure
javax.security.sasl.SaslException: GSS initiate failed [Caused by GSSException: No valid credentials provided (Mechanism level: Failed to find any Kerberos tgt)]
    at com.sun.security.sasl.gsskerb.GssKrb5Client.evaluateChallenge(GssKrb5Client.java:212)
    at org.apache.thrift.transport.TSaslClientTransport.handleSaslStartMessage(TSaslClientTransport.java:94)
    at org.apache.thrift.transport.TSaslTransport.open(TSaslTransport.java:271)
    at org.apache.thrift.transport.TSaslClientTransport.open(TSaslClientTransport.java:37)
    at org.apache.hadoop.hive.thrift.client.TUGIAssumingTransport$1.run(TUGIAssumingTransport.java:52)
    at org.apache.hadoop.hive.thrift.client.TUGIAssumingTransport$1.run(TUGIAssumingTransport.java:49)
    at java.security.AccessController.doPrivileged(Native Method)
    at javax.security.auth.Subject.doAs(Subject.java:415)

看来通过客户端的代理是不行了,此时就要祭出hiveserver2对于平台端一个非常重要的参数:hive.server2.proxy.user,仔细思考一下其实对于hiveserver2而言,它需要知道客户端的用户名,最直接的方式就是使用当前认证的用户执行,那么hiveserver2得到的用户名就是该连接中kerberos的认证用户,而对于代理执行的情况,如果当前连接的kerberos是一个可代理的账号,那么就可以通过hive.server2.proxy.user参数传递真正的代理用户,这样就不需要任何ugi的操作。使用该参数的前提仍然是当前的kerberos用户具有可代理权限,如果一个普通用户使用该参数创建连接,会出现如下错误:

> beeline -u "jdbc:hive2://db-53.photo.163.org:10000/default;principal=hive/[email protected];hive.server2.proxy.user=da"
Connecting to jdbc:hive2://db-53.photo.163.org:10000/default;principal=hive/[email protected];hive.server2.proxy.user=da
Error: Failed to validate proxy privilege of nrpt for da (state=08S01,code=0)
Beeline version 1.2.1 by Apache Hive
0: jdbc:hive2://db-53.photo.163.org:10000/def (closed)> 

而如果当前kerberos账号是可代理的用户,执行连接则能够成功并且可以以被代理的用户身份执行SQL:

> kinit -kt hive.keytab  hive/[email protected]
> beeline -u "jdbc:hive2://db-53.photo.163.org:10000/default;principal=hive/[email protected];hive.server2.proxy.user=nrpt"
Connecting to jdbc:hive2://db-53.photo.163.org:10000/default;principal=hive/[email protected];hive.server2.proxy.user=nrpt
Connected to: Apache Hive (version 1.2.1)
Driver: Hive JDBC (version 1.2.1)
Transaction isolation: TRANSACTION_REPEATABLE_READ
Beeline version 1.2.1 by Apache Hive
0: jdbc:hive2://db-53.photo.163.org:10000/def>

讨论到这里对于平台端如何使用hiveserver2代理任意用户执行查询已经比较清晰了,总结一下就是hiveserver2开启doAs的选项,平台端通过加入hive.server2.proxy.user参数代理任意用户执行查询,不需要拥有任何用户的keytab。但是这里还是存在一个问题,那就是不同用户的连接URL是不同的,这样服务端需要对每一个用户维护一个连接池,或者比较暴力的做法就是每次查询新创建一个connection,执行完成之后销毁该连接。

以上探讨了hiveserver2在使用过程中的代理方式,但是spark和impala就没有这么完善的功能了,下文再详细梳理impala是怎么做的,以及如何能够修改使其实现hiveserver2类似的功能。

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/yu616568/article/details/54969729

智能推荐

动手学习TCP:TCP连接建立与终止_dengji7657的博客-程序员信息网

TCP是一个面向连接的协议,任何一方在发送数据之前,都必须先在双方之间建立一条连接。所以,本文就主要看看TCP连接的建立和终止。在开始介绍TCP连接之前,先来看看TCP数据包的首部,首部里面有很多重要的字段,在我们实现程序的时候需要进行设置。TCP的首部在OSI七层模型中,上层的数据包都会作为下层数据包的数据部分(payload)。也就是说,当构造TCP数据包的时候,会把...

spring + mybtis 事务详解(connection一致性)_小小小程序员2019的博客-程序员信息网

一、spring IOC容器会为添加了@Transaction注解的方法进行事务增强(动态代理)在调用方法之前会调用TransactionInterceptor的invoke方法:又会调用到父类TransactionAspectSupport的invokeWithinTransaction方法,主要关注createTransactionIfNecessary进入该方法会调用...

Android与Ros通信详解-2.RosBridge_ideal_generation的博客-程序员信息网_android rosbridge接收多个节点数据

RosBridge底层通过Websocket以Json格式进行通信。在Ros端安装服务,在Android端实现Websocket,完成和Ros端的通信。ROS服务端安装suite服务sudo apt-get install ros-&lt;rosdistro&gt;-rosbridge-suite启动roslaunch rosbridge_server rosbridge_websocket.launchAndroid端Android端使用了一个github上的开源项目,RosBridge

嵌入式linux入门3-3-套接字_lczdk的博客-程序员信息网_嵌入式套接字

个人博客对应地址:嵌入式linux入门3-3-套接字socket主要函数创建套接字socket,我们一般翻译为套接字,其是一种通讯接口,允许位于不同计算机之间的线程通过网络进行通讯,我们可以使用socket系统调用来创建一个socket接口,此函数会返回一个定位此接口的文件描述符。/** * 创建一个socket接口,并返回它的描述符,返回-1表示失败 * * domain参数用于指定接口使用的通讯域(communication domain),其支持AF_xxx形式的一组宏定义, * 对

Icepak打开TZR文件_51CAE的博客-程序员信息网

唐深51CAETZR文件TZR文件是ANSYSIcepak的项目打包文件,包含重建Icepak工程所必须的Job,Model和Problem文件。ANSYS官方客服端网站提供大量的TZR文件供客户下载,需要注意的是,TZR文件并不包含网格和计算结果。TZR文件打开方法(一)依次点击【开始】-&gt;【ANSYS 19.0】-&gt;【ANSYSI...

浅谈C语言嵌入式系统编程注意事项_jieniyimiao的博客-程序员信息网

C语言嵌入式系统编程注意事项之背景篇 本文的讨论主要围绕以通用处理器为中心的协议处理模块进行,因为它更多地牵涉到具体的C语言编程技巧  不同于一般形式的软件编程,嵌入式系统编程建立在特定的硬件平台上,势必要求其编程语言具备较强的硬件直接操作能力。无疑,汇编语言具备这样的特质。但是,归因于汇编语言开发过程的复杂性,它并不是嵌入式系统开发的一般选择。而与之相比,C语言--一种"高级的低级"语言,则成为

随便推点

Win10关闭蓝牙省电模式的两种方法_我是小吕啊的博客-程序员信息网_蓝牙省电模式怎么关闭

windows10会默认开启蓝牙省电模式,这就会导致如果长时间不用蓝牙设备(其实也就15分钟左右),蓝牙就会断开连接,这个时候就又要重连一次蓝牙。所以这里记录一下如何关闭Win10的蓝牙省电模式,顺便开启“允许蓝牙设备查找这台电脑”的功能

如何将PEM证书转换成JKS证书_$海阔天空$的博客-程序员信息网_pem转jks

在使用SSL/TLS进行通信的时候,经常需要加载OpenSSL生成的PEM格式证书。由于Java的JDK不支持直接加载PEM格式的证书,所以需要将PEM格式证书转换成Java能够直接加载的JKS格式证书。使用OpenSSL生成自签发的PEM证书可以参考此篇文章:[**OpenSSL Certificate Authority ]**(https://jamielinux.com/docs/openssl-certificate-authority/index.html)假设有三个PEM证书文件:ca.

MySQL数据库-数据的分组操作(group by)命令演示_HXH.py的博客-程序员信息网_groupby命令

分组 group bygroup by# 对原始数据筛选 分组 在聚合函数的基础上分组,否则没有意义按照性别分组, 查询所有的性别select gender from students group by gender;失败select * from students group by gender;失败 select name from students group by gen...

互联网测试岗位分类_互联网公司职位架构_狗蛋家的男人的博客-程序员信息网

一篇文章看懂互联网公司职位架构以下是最通俗的一张互联网公司职位架构图:那么,今天我就简单说说各项职能下,各个职位可能重点落在哪些事务上。1产品助理「产品助理」是一个在大公司里才会出现的岗位。这个职位设立的初衷,是解放产品经理,让产品经理从繁杂的会议、扯皮、文档写作中解放出来,专心做需求分析和产品设计。2产品经理「产品经理」的具体职能是落在对用户需求的深刻理解上的,并且通过逻辑思维和体验优化来让客户...

推荐文章

热门文章

相关标签