hbas报错: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:高效的二进制序列化协议。

是hbase该版本自带的问题

原因1: 客户端链接hbase时传输协模式与协议与thriftpy服务端不匹配。可更改为 h_conn = happybase.Connection( host=“host”,port=port, transport=‘framed’, protocol=‘compact’ )

原因二:操作完hbase时with不会默认close thriftpy的socket链接,而HBASE的服务端有默认为60秒的超时后会主动断开,而操作者的连接池不知道,导致TTransportException(type=4, message=‘TSocket read 0 bytes’) 这个错误

原因三:第三个原因与第二个类似,但是现象有所不同。我简单的描述一下现象:当首次初始化好happybase连接池后,一直未操作查数据,过一会后,大概60秒再操作会出现标题中的问题。 原因是,happybase默认初始化链接池后,会默认去向hbase做一次链接(如下图),但为close,我个人认为这也是happybase这个包的bug。解决这个问题的办法就是,初始化好链接后,立刻做一次查询(比如查看hbase有哪些表)后close掉这个链接。可能大家会问,做查询的这个链接怎么保证就是happybase初始化的那个链接,其实只要看看源码就知道,happybase的连接池是维护的一个队列,所以第一次查询肯定是这个happybase包默认初始化而未释放的链接

(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')

即在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>86400000</value>

</property>


也可以尝试使用hbase连接池的方式

原因:想保持hbase 默认的配置不动,代码里 就来一个新的数据 就新建一个连接 等写入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() 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()

但我使用连接池还出现了这个问题,可能原因:再次打开连接的时候,我们就可以重用上次的连接。如果在这个时间内没有连接请求(打开连接),这个数据库连接将被关闭,并从连接池中移除这个连接实例。如果池中连接到达了最大连接数,请求进入等待队列直到空闲连接可用。如果在可获取连接对象之前超时期限已过(由 Connect Timeout 连接字符串属性来决定),则将出错。

Timeout:

HBase之超时机制 客户端超时设置对整个系统的稳定性以及敏感性至关重要,一旦没有超时设置或超时时间设置过长,服务器端的长时间卡顿必然会引起客户端阻塞等待,进而影响上层应用。好在HBase提供了多个客户端参数设置超时,主要包括 hbase.rpc.timeout / hbase.client.operation.timeout/ hbase.client.scanner.timeout.period

问题:

1.hbase60s服务端关闭,会自动重启连接吗?还是代码重启

2.应用连接池可以创建多个连接,但还会报这个错的原因是:同一时刻创建的连接池都同时超时还没来得及新建连接吗?

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值