编辑:此问题和答案适用于遇到主题行中所述异常的任何人:TTransportException(type = 4,message ='TSocket read 0 bytes');是否涉及Cloudera和/或HappyBase。
根本问题(事实证明)源于
protocol
上的transport
和/或client-side
格式与server-side
正在实现的不匹配,这可能发生在任何客户端/服务器配对上。我刚好碰巧是Cloudera和HappyBase,但是你不必是,你可以遇到同样的问题。
有没有人最近尝试使用happybase v1.1.0 (latest)
Python包与Hbase
上的Cloudera CDH v6.1.x
进行交互?
我正在尝试各种选项,但不断获得异常:
thriftpy.transport.TTransportException:
TTransportException(type=4, message='TSocket read 0 bytes')
这是我如何开始一个会话并提交一个简单的调用来获取表的列表(使用Python v3.6.7
:
import happybase
CDH6_HBASE_THRIFT_VER='0.92'
hbase_cnxn = happybase.Connection(
host='vps00', port=9090,
table_prefix=None,
compat=CDH6_HBASE_THRIFT_VER,
table_prefix_separator=b'_',
timeout=None,
autoconnect=True,
transport='buffered',
protocol='binary'
)
print('tables:', hbase_cnxn.tables()) # Exception happens here.
以下是Cloudera CDH v6.1.x
如何启动Hbase Thrift
服务器(为简洁而截断):
/usr/java/jdk1.8.0_141-cloudera/bin/java [... snip ... ] \
org.apache.hadoop.hbase.thrift.ThriftServer start \
--port 9090 -threadpool --bind 0.0.0.0 --framed --compact
我已经尝试了几种不同的选项,但无处可去。
有没有人有这个工作?
编辑:我接下来编译Hbase.thrift
(来自Hbase
源文件 - 与HBase
使用相同的CDH v6.1.x
版本)并使用Python thrift
绑定包(换句话说,我从等式中删除了happybase
)并获得了相同的异常。
(._.);
谢谢!
经过一天的努力,我的问题的答案如下:
import happybase
CDH6_HBASE_THRIFT_VER='0.92'
hbase_cnxn = happybase.Connection(
host='vps00', port=9090,
table_prefix=None,
compat=CDH6_HBASE_THRIFT_VER,
table_prefix_separator=b'_',
timeout=None,
autoconnect=True,
transport='framed', # Default: 'buffered' <---- Changed.
protocol='compact' # Default: 'binary' <---- Changed.
)
print('tables:', hbase_cnxn.tables()) # Works. Output: [b'ns1:mytable', ]
请注意,虽然这个Q&A是在Cloudera
的背景下构建的,但事实证明(正如您将看到的)这是Thrift
版本和Thrift
服务器端配置相关,因此它也适用于Hortonworks
和MapR
用户。
说明:
在Cloudera CDH v6.1.x
(也可能是未来版本)上,如果你访问其管理U.I.的Hbase Thrift Server Configuration
部分,你会发现 - 在许多其他设置中 - 这些:
请注意,compact protocol
和framed transport
都已启用;所以他们相应地需要在happybase
中更改其默认值(我在上面显示)。
正如EDIT对我最初问题的后续跟进所提到的,我还调查了一个纯粹的Thrift
(非happybase
)解决方案。对于这种情况的Python代码的类似更改,我也可以使用它。以下是您应该用于纯Thrift
解决方案的代码(注意阅读下面的注释注释):
from thrift.protocol import TCompactProtocol # Notice the import: TCompactProtocol [!]
from thrift.transport.TTransport import TFramedTransport # Notice the import: TFramedTransport [!]
from thrift.transport import TSocket
from hbase import Hbase
# -- This hbase module is compiled using the thrift(1) command (version >= 0.10 [!])
# and a Hbase.thrift file (obtained from http://archive.apache.org/dist/hbase/
# -- Also, your "pip freeze | grep '^thrift='" should show a version of >= 0.10 [!]
# if you want Python3 support.
(host,port) = ("vps00","9090")
transport = TFramedTransport(TSocket.TSocket(host, port))
protocol = TCompactProtocol.TCompactProtocol(transport)
client = Hbase.Client(protocol)
transport.open()
# Do stuff here ...
print(client.getTableNames()) # Works. Output: [b'ns1:mytable', ]
transport.close()
我希望这能让人们痛苦地度过难关。 = :)
鸣谢: