hbase报错TTransportException(type=4,message=’TSocket read 0 bytes’)解决方案
(1)报错信息:
thrift.transport.TTransport.TTransportException: TSocket read 0 bytes
(2)产生原因:
可能是因为thrift 的server端和client端的协议不匹配造成的。
Python要使用TCompactProtocol,而不能使用TBinaryProtocol。
TBinaryProtocol:缺省简单的二进制序列化协议。
TCompactProtocol:高效的二进制序列化协议。
(3)解决办法:
1.在服务端修改hbase-site.xml,增加TFramedTransport和TCompactProtocol功能,即:
<property>
<name>hbase.regionserver.thrift.framed</name>
<value>true</value>
</property>
<property>
<name>hbase.regionserver.thrift.compact</name>
<value>true</value>
</property>
2.然后重启thrift:$HBASE_HOME/bin/hbase-daemon.sh restart thrift
3.在客户端建立连接时增加protocol,transport参数:
conn = happybase.Connection(host="10.255.111.92",port=9090)
#修改为:
conn = happybase.Connection(host="10.255.111.92",port=9090,protocol='compact',transport='framed')
(4)然而问题并没有解决!!!(重点)
经过测试脚本测试(建立连接往Hbase写入一条数据然后time.sleep(601)之后再次写入一条数据)发现又出现了TTransportException(type=4, message=‘TSocket read 0 bytes’)的报错,继续排查原因。
看到一个网页内容:
问题背景
测试环境是三台服务器搭建的Hadoop分布式环境。Hadoop版本是:hadoop-2.7.3;Hbase-1.2.4;
zookeeper-3.4.9。
使用thrift c++接口向hbase中写入数据,每次都是刚开始写入正常,过一段时间就开始报错。
但之前使用的hbase-0.94.27版本就没遇到过该问题,配置也相同,一直用的好好地。
thrift接口报错
解决办法
通过抓包可以看出,hbase server响应了RST包,导致连接中断。
通过 bin/hbase thrift start -threadpool命令可以readTimeout的设置为60s。
thriftpool
经过验证却是和这个设置有关,配置中没有配置过该项,通过查看代码发现60s是默认值,如果没有配置即按照以该值为准。
因此在conf/hbase-site.xml中添加上配置即可:
<property>
<name>hbase.thrift.server.socket.read.timeout</name>
<value>6000000</value>
<description>eg:milisecond</description>
</property>
然而问题在一段时间之后又一次出现了,又开始了查找原因发现是hbase该版本自带的问题,它将所有连接(不管有没有在使用)都默认为idle的状态,然后有个hbase.thrift.connection.max-idletime的配置,所以我将此项配置为31104000(一年),问题解决了!
解决方法
即在hbase-site.xml增加了如下内容,并重新启动thrift和hbase,问题得到解决
<property>
<name>hbase.thrift.server.socket.read.timeout</name>
<value>6000000</value>
</property>
<property>
<name>hbase.thrift.connection.max-idletime</name>
<value>31104000</value>
</property>
2021年1月15更新:
问题又一次出现了,经过了多次尝试hbase.thrift.server.socket.read.timeout参数并不是秒为单位的
当将该值设置为70000时候 通过脚本向HBase写入数据间隔69秒写入一次 没有报错 但将间隔时间设置为71秒之后又出现了thriftpy2.transport.base.TTransportException: TTransportException(type=4, message=‘TSocket read 0 bytes’)的报错,所以推测出hbase.thrift.server.socket.read.timeout参数的单位为毫秒 我将此参数设置成了86400000(一天)问题得到了解决
<property>
<name>hbase.thrift.server.socket.read.timeout</name>
<value>86400000</value>
</property>
<property>
<name>hbase.thrift.connection.max-idletime</name>
<value>31104000</value>
</property>
2022年6月9日更新:
可以尝试使用hbase连接池的方式(待验证)
import happybase
import json
# 通过size控制连接池中的连接数量
pool = happybase.ConnectionPool(size=3,host="10.255.111.92",port=9090,protocol='compact',transport='framed')
# 从连接池中取出一个连接
with pool.connection() as conn:
table = conn.table('test_table')
# TODO 执行操作
pass
# 操作完成 及时close 保证每次操作都是一个新启动的连接
conn.close()
参考链接:
https://blog.51cto.com/13103353/2107257