我们在python中有etl作业(luigi)。它们都连接到hivemetastore以获取分区信息。
代码:
from hive_metastore import ThriftHiveMetastore
client = ThriftHiveMetastore.Client(protocol)
partitions = client.get_partition_names('sales', 'salesdetail', -1)
-1是最大\u部分(返回的最大分区数)
它会这样随机超时:
File "/opt/conda/envs/etl/lib/python2.7/site-packages/luigi/contrib/hive.py", line 210, in _existing_partitions
partition_strings = client.get_partition_names(database, table, -1)
File "/opt/conda/envs/etl/lib/python2.7/site-packages/hive_metastore/ThriftHiveMetastore.py", line 1703, in get_partition_names
return self.recv_get_partition_names()
File "/opt/conda/envs/etl/lib/python2.7/site-packages/hive_metastore/ThriftHiveMetastore.py", line 1716, in recv_get_partition_names
(fname, mtype, rseqid) = self._iprot.readMessageBegin()
File "/opt/conda/envs/etl/lib/python2.7/site-packages/thrift/protocol/TBinaryProtocol.py", line 126, in readMessageBegin
sz = self.readI32()
File "/opt/conda/envs/etl/lib/python2.7/site-packages/thrift/protocol/TBinaryProtocol.py", line 206, in readI32
buff = self.trans.readAll(4)
File "/opt/conda/envs/etl/lib/python2.7/site-packages/thrift/transport/TTransport.py", line 58, in readAll
chunk = self.read(sz - have)
File "/opt/conda/envs/etl/lib/python2.7/site-packages/thrift/transport/TTransport.py", line 159, in read
self.__rbuf = StringIO(self.__trans.read(max(sz, self.__rbuf_size)))
File "/opt/conda/envs/etl/lib/python2.7/site-packages/thrift/transport/TSocket.py", line 105, in read
buff = self.handle.recv(sz)
timeout: timed out
这种错误偶尔发生。
配置单元元存储上有15分钟超时。
当我研究单独运行get\u partition\u names时,它会在几秒钟内返回数据。
即使我将socket.timeout设置为1或2秒,查询也会完成。
配置单元元存储日志中没有套接字关闭连接消息的记录 cat /var/log/hive/..log.out
它通常超时的表有大量分区~10k+。但如前所述,它们只是随机超时。当单独测试代码部分时,它们会快速返回分区元数据。
你知道为什么它会随机超时,或者如何在metastore日志中捕获这些超时错误,或者如何修复它们吗?
1条答案
按热度按时间7ivaypg91#
问题是luigi中的线程重叠
我们使用一个单例来实现一个穷人的连接池。但是luigi的不同工作线程相互攻击,当一个线程的get\u分区\u名称与另一个线程的get\u名称冲突时,会导致奇怪的行为。
我们通过确保每个线程的连接对象在连接池中获得自己的“key”(而不是所有线程共享进程id key)解决了这个问题