简体   繁体   English

Cloudera/CDH v6.1.x + Python HappyBase v1.1.0: TTransportException(type=4, message='TSocket read 0 bytes')

[英]Cloudera/CDH v6.1.x + Python HappyBase v1.1.0: TTransportException(type=4, message='TSocket read 0 bytes')

EDIT: This question and answer applies to anyone who is experiencing the exception stated in the subject line: TTransportException(type=4, message='TSocket read 0 bytes') ;编辑:此问题和答案适用于遇到主题行中所述异常的任何人: TTransportException(type=4, message='TSocket read 0 bytes') ; whether or not Cloudera and/or HappyBase is involved.无论是否涉及 Cloudera 和/或 HappyBase。

The root issue (as it turned out) stems from mismatching protocol and/or transport formats on the client-side with what the server-side is implementing, and this can happen with any client/server paring.根的问题(因为它变成了)从失配茎protocol和/或transport的格式的client-side与什么server-side被执行,并且这可以与任何客户端/服务器配对发生。 Mine just happened to be Cloudera and HappyBase, but yours needn't be and you can run into this same issue.我的恰好是Cloudera 和 HappyBase,但您的不一定是,而且您可能会遇到同样的问题。

Has anyone recently tried using the happybase v1.1.0 (latest) Python package to interact with Hbase on Cloudera CDH v6.1.x ?有没有人使用了最近尝试happybase v1.1.0 (latest) Python包与互动HbaseCloudera CDH v6.1.x

I'm trying various options with it, but keep getting the exception:我正在尝试各种选项,但不断收到异常:

thriftpy.transport.TTransportException:
TTransportException(type=4, message='TSocket read 0 bytes')

Here is how I start a session and submit a simple call to get a listing of tables (using Python v3.6.7 :下面是我如何开始一个会话并提交一个简单的调用来获取表列表(使用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.

And here is how Cloudera CDH v6.1.x starts the Hbase Thrift server (truncated for brevity):以下是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

I've tried several variations to options, but getting nowhere.我尝试了几种选项的变体,但一无所获。

Has anyone ever got this to work?有没有人让这个工作?

EDIT : I next compiled Hbase.thrift (from the Hbase source files -- same HBase version as used by CDH v6.1.x ) and used the Python thrift bindings package (in other words, I removed happybase from the equation) and got the same exception.编辑:我接下来编译了Hbase.thrift (来自Hbase源文件——与CDH v6.1.x使用的HBase版本相同)并使用了 Python thrift绑定包(换句话说,我从等式中删除了happybase )并得到同样的例外。

(._.); (._.);

Thank you!谢谢!

After a days worth of working on this, the answer to my question is the following: 经过一天的努力,我的问题的答案如下:

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', ]

Note that although this Q&A was framed in the context of Cloudera , it turns out (as you'll see) that this was Thrift versions and Thrift Server-Side configurations related, and so it applies to Hortonworks and MapR users, too. 请注意,尽管此问与答是在Cloudera的上下文中进行的,但事实证明(如您所见),这是Thrift版本和Thrift Server-Side配置相关的,因此它也适用于HortonworksMapR用户。

Explanation : 说明

On Cloudera CDH v6.1.x (and probably future versions, too) if you visit the Hbase Thrift Server Configuration section of its management UI, you'll find -- among many other settings -- these: Cloudera CDH v6.1.x (可能还有将来的版本)上,如果您访问其管理UI的“ Hbase Thrift Server Configuration部分, Hbase Thrift Server Configuration在许多其他设置中找到以下这些:


CDH6.1.x Hbase Thrift服务器配置U.I.

Notice that compact protocol and framed transport are both enabled; 请注意,同时启用了compact protocolframed transport so they correspondingly needed to be changed in happybase from its defaults (which I show above). 因此相应地需要在happybase其更改为默认值(我在上面显示)。

As mentioned in EDIT follow-up to my initial question, I also investigated a pure Thrift (non happybase ) solution. 如我对第一个问题的EDIT后续讨论中所述,我还研究了一个纯Thrift (非happybase )解决方案。 And with analogous changes to Python code for that case, I got that to work, too. 在这种情况下,通过对Python代码进行类似的更改,我也可以正常工作。 Here is the code you should use for the pure Thrift solution (taking care to read my commented annotations below): 这是您应该用于纯Thrift解决方案的代码(请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()

I hope this spares people the pain I went through. 我希望这可以减轻人们的痛苦。 =:) = :)

CREDITS : 学分

I also encountered this problem when I was using CDH 6.3.2 HBase recently.我最近在使用CDH 6.3.2 HBase时候也遇到了这个问题。 It is not enough to follow the above configuration.仅遵循上述配置是不够的。 Also need to close hbase.regionserver.thrift.http and hbase.thrift.support.proxyuser in order to connect successfully还需要关闭hbase.regionserver.thrift.httphbase.thrift.support.proxyuser才能连接成功

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM