thrift的TTransport连接池注意事项[Java版本说明]

thrift长连接,基于维护TTransport连接池实现。

一般步骤:

1.对要通信的服务器ip和port,创建足够的TTransport实例并维护起来。

2.在通信的时候,从中选择空闲的TTransport连接使用。

3.通信结束后归还TTransport实例,以供下次使用。

bug描述:

在上面的3步骤中,如果在通信过程中所发生的超时异常(SocketTimeoutException),仅仅是捕获和归还TTransport资源并且供下次服务通信使用。

就有可能会出现这次所超时的请求的返回结果,会被下个使用该TTransport进行通信所获取到。

这个奇怪的现象可以这样描述,假设A使用了TTransport-1进行了通信,原本应该返回结果A,但是由于超时,该A归还了TTransport-1资源,

接着到B需要通信,恰好拿到了TTransport-1进行通信,预期结果是B。但这时候TTransport-1上次超时的A请求返回了结果A,这时候B会接受到A结果。


原因是:

TTransport transport = new TFramedTransport(new TSocket(ip, port, timeout));

TTransport是使用TSocket进行通信的,而TSocket其实是Socket的封装

socket_ = new Socket();
try {
      socket_.setSoLinger(false, 0);
      socket_.setTcpNoDelay(true);
      socket_.setKeepAlive(true);
      socket_.setSoTimeout(socketTimeout_);
} catch (SocketException sx) {
      LOGGER.error("Could not configure socket.", sx);
 }

而TSocket所传输的timeout就是Socket里面的setSoTimeout,而该方法的java描述为:

*  Enable/disable {@link SocketOptions#SO_TIMEOUT SO_TIMEOUT}
     *  with the specified timeout, in milliseconds. With this option set
     *  to a non-zero timeout, a read() call on the InputStream associated with
     *  this Socket will block for only this amount of time.  If the timeout
     *  expires, a <B>java.net.SocketTimeoutException</B> is raised, though the
     *  Socket is still valid.
The option <B>must</B> be enabled
     *  prior to entering the blocking operation to have effect. The
     *  timeout must be {@code > 0}.
     *  A timeout of zero is interpreted as an infinite timeout.

这里的意思大致是socket请求超时了,会抛出SocketTimeoutException,但是原来的Socket仍然有效,也就意味着之前所超时的请求,如果服务器继续返回结果,

客户端没有关闭的Socket是能够继续收到结果数据的。

因此对于超时而又继续使用的Socket会有可能继续接受到之前的旧结果。也就会出现上面thrift长连接使用TTranposrt通信,如果仅仅是对于超时的TTransport归还资源供下次通信使用,就有可能会出现上面所描述的bug现象了。


我的做法:

对于出现超时异常,TTransport直接进行close操作,避免被其他通信使用出现异常。

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 8
    评论
以下是连接Hive的Java代码: ``` import org.apache.hadoop.conf.Configuration; import org.apache.hadoop.security.UserGroupInformation; import org.apache.thrift.TException; import org.apache.thrift.protocol.TBinaryProtocol; import org.apache.thrift.transport.TSocket; import org.apache.thrift.transport.TTransport; import org.apache.thrift.transport.TTransportException; import org.apache.hadoop.hive.metastore.api.*; public class HiveClient { private static String host = "localhost"; private static int port = 9083; public static void main(String[] args) throws TException { // Set Hadoop configuration Configuration conf = new Configuration(); conf.set("hadoop.security.authentication", "Kerberos"); // Set Kerberos security System.setProperty("java.security.krb5.realm", "EXAMPLE.COM"); System.setProperty("java.security.krb5.kdc", "kdc.example.com"); UserGroupInformation.setConfiguration(conf); UserGroupInformation.loginUserFromKeytab("[email protected]", "/path/to/user.keytab"); // Connect to Hive Metastore service TTransport transport = new TSocket(host, port); transport.open(); TBinaryProtocol protocol = new TBinaryProtocol(transport); ThriftHiveMetastore.Client client = new ThriftHiveMetastore.Client(protocol); // Get list of databases List<String> databases = client.get_all_databases(); for (String database : databases) { System.out.println(database); } // Close connection transport.close(); } } ``` 需要注意的是,代码中涉及到了Kerberos认证和安全配置,需要根据实际情况进行调整。同时,需要根据实际的Hive Metastore服务地址和端口进行设置。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值