华为大数据平台使用pyhive连接hive的方法(Kerberos验证)
提示:轉載請附原文鏈接
文章目錄
- 前言
- 一、準備工作
- 二、處理過程
- 1. 前期報錯情況
- 2. 修改源碼并測試
- 2.1 分析一下需要修改哪些位置
- 2.2 修改源碼
- 2.3 從源碼安裝pyhive并測試
- 三、踩坑
- 1. 環境引入問題
- 總結
前言
近期想用python寫個數據任務的調度工具,使用pyhive連接華為大數據平臺的hive不成功,在彭老師的協助下最終完成了hive的連接,特此記錄一下過程。
一、準備工作
-
PyHive源碼包:我用的 PyHive-0.6.5
-
安裝系統依賴(CentOS,其他linux類似): yum安裝以下包,cyrus-sasl、cyrus-sasl-lib、cyrus-sasl-devel、cyrus-sasl-md5、cyrus-sasl-plain、cyrus-sasl-gssapi (Kerberos需要用GSSAPI, 來自cyrus-sasl-gssapi)
運行sasl2-shared-mechlist命令包含GSSAPI應該就可以了
二、處理過程
1. 前期報錯情況
代碼如下(ip、端口、主機名均替換為非真實值):
from pyhive import hive conn = hive.Connection(host="hive_server2_host", port=10000, auth="KERBEROS", kerberos_service_name="hive")報錯如下:
TTransportException Traceback (most recent call last) /tmp/ipykernel 23431/908701831.py in <module> ----> 1 conn = hive.Connection(host=”hive_server2_host", port=10000, auth="KEBEROS", kerberos_service_name="hive" ) /data/anaconda3/lib/python3.9/site-packages/PyHive-0.6.5-py3.9. egg/pyhive/hive.py in __init__ (self, host, port, scheme, username, database, auth, configuration, kerberos_ service_name, password, check_hostname, ssl_cert, thrift_transport)241242 try: --> 243 self._transport.open()244 open_session_req = ttypes.TOpenSessionReq(245 client protocol=protocol version,/data/anaconda3/lib/python3.9/site-packages/thrift_sasl/__init__.py in open(self)82 ret, chosen_mech, initial_response = self.sasl.start(self.mechanism)83 if not ret: --> 84 raise TTransportException(type=TTransportException.NOT_OPEN,85 message=("Could not start SASL: %s" % self.sasl.getError()))86TTransportException: Could not start SASL: b'Error in sasl_client_start (-1) SASL(-1): generic failure: GSSAPI Error: Unspecified GSS failure. Minor code may provide more information (Server hive/hive_server2_host@FI1.COM not found in Kerberos database)簡要分析:報錯中提示“Server hive/hive_server2_host@FI1.COM not found in Kerberos database”,但我實際使用beeline的時候,看到的提示是:“Connecting to jdbc:hive2://…;principle=hive/hadoop_fi1_host@FI1.COM”,那么可能需要修改pyhive源碼,嘗試讓驗證時使用“hadoop_fi1_host”的priciple而不是“hive_server2_host”
2. 修改源碼并測試
2.1 分析一下需要修改哪些位置
解壓:PyHive-0.6.5.tar.gz,然后找到目錄下的 pyhive/hive.py。從以上報錯可以看到,在self._transport.open()時產生了錯誤,那么我們找到使用KERBEROS認證時源碼中哪里定義了self._transport:
if auth == 'NOSASL':# NOSASL corresponds to hive.server2.authentication=NOSASL in hive-site.xmlself._transport = thrift.transport.TTransport.TBufferedTransport(socket)elif auth in ('LDAP', 'KERBEROS', 'NONE', 'CUSTOM'):# Defer import so package dependency is optionalimport saslimport thrift_saslif auth == 'KERBEROS':# KERBEROS mode in hive.server2.authentication is GSSAPI in sasl librarysasl_auth = 'GSSAPI'else:sasl_auth = 'PLAIN'if password is None:# Password doesn't matter in NONE mode, just needs to be nonempty.password = 'x'def sasl_factory():sasl_client = sasl.Client()# 這里 第217行sasl_client.setAttr('host', host)if sasl_auth == 'GSSAPI':sasl_client.setAttr('service', kerberos_service_name)elif sasl_auth == 'PLAIN':sasl_client.setAttr('username', username)sasl_client.setAttr('password', password)else:raise AssertionErrorsasl_client.init()return sasl_client# 這里 第227行self._transport = thrift_sasl.TSaslClientTransport(sasl_factory, sasl_auth, socket)第227行的self._transport = thrift_sasl.TSaslClientTransport(sasl_factory, sasl_auth, socket)中,sasl_factory是一個函數,用來創建sasl_client并設置相關屬性。然后可以看到第217行設置了sasl的hostsasl_client.setAttr('host', host)。
另外在源碼中發現與Kerberos相關的host設置的地方還有(第160行):
elif auth == "KERBEROS" and kerberos_service_name:self._set_kerberos_header(thrift_transport, kerberos_service_name, host)對Kerberos了解不多,因此不確定此處是否需要修改,如果前面那處不行再作嘗試。
2.2 修改源碼
修改 class Connection 的 __init__函數,添加krb_host參數,如下所示:
class Connection(object):"""Wraps a Thrift session"""def __init__(self,host=None,port=None,scheme=None,username=None,database='default',auth=None,configuration=None,kerberos_service_name=None,password=None,check_hostname=None,ssl_cert=None,thrift_transport=None,krb_host=None):修改sasl_factory()函數(sasl_client.setAttr('host', host)處如果krb_host不為None就使用krb_host):
def sasl_factory():sasl_client = sasl.Client()if krb_host is not None:sasl_client.setAttr('host', krb_host)else:sasl_client.setAttr('host', host)if sasl_auth == 'GSSAPI':sasl_client.setAttr('service', kerberos_service_name)elif sasl_auth == 'PLAIN':sasl_client.setAttr('username', username)sasl_client.setAttr('password', password)else:raise AssertionErrorsasl_client.init()return sasl_client2.3 從源碼安裝pyhive并測試
# 卸載原有的 pip uninstall pyhive # 從源碼安裝 cd PyHive-0.6.5 python setup.py install測試情況
from pyhive import hiveconn = hive.Connection(host="hive_server2_host", port=10000, auth="KERBEROS", kerberos_service_name="hive",krb_host="hadoop_fi1_host" ) cursor = conn.cursor() cursor.execute("show databases") print(cursor.fetchone()) cursor.close() conn.close()結果如下:
('default',)成功!
三、踩坑
1. 環境引入問題
第一次按上述方法修改完成后依然報錯:
TTransportException: Could not start SASL: b'Error in sasl_client_start (-1) SASL(-1): generic failure: GSSAPI Error: Unspecified GSS failure. Minor code may provide more information (Cannot find KDC for realm "FI1.COM")一度以為以上的修改思路不對,百般嘗試都不順利。后在彭老師提醒下可能是環境引入的問題(我在jupyter中使用os.system或subprocess嘗試的環境引入),建議在終端中先引入環境再在python中嘗試。
然后在終端中嘗試:
[user@centos ~]$ source /opt/hadoop_client/bigdata_env [user@centos ~]$ kinit -kt ~/etc/user.keytab username [user@centos ~]$ python >>> from pyhive import hive >>> conn = hive.Connection(host="hive_server2_host", port=10000, auth="KERBEROS", kerberos_service_name="hive", krb_host="hadoop_fi1_host")一切正常,不再報錯。
分析原因應該是,使用的 os.system 運行的 source 和 kinit,運行的效果都在 os.system 新建的進程中,而不是作用于當前運行python的進程中,所以導致了不生效。
還有一個導致我一直測試不出來的就是是使用nohup在后臺運行的jupyter服務,服務起得很早,后面大數據平臺配置有變更,而我沒有重啟jupyter服務。
不管是運行python文件或開jupyter,都要先引入環境,然后再運行py文件或jupyter。
總結
以上就是本次記錄的內容,特別注意的是環境引入的坑。
感謝彭老師花費時間協助解決問題。
總結
以上是生活随笔為你收集整理的华为大数据平台使用pyhive连接hive的方法(Kerberos验证)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: add a redfish schema
- 下一篇: oc语言的优缺点有哪些