这篇文章上次修改于 531 天前,可能其部分内容已经发生变化,如有疑问可询问作者。

thrift 在部分环境下连接服务端慢的问题

我使用的 thrift 版本为 0.14.2.0,平台为 .Net,当我使用如下代码创建一个客户端代理对象时在某些情况下会非常慢:

private async Task<T> CreateClientAsync<T>(string host, int port) where T : TBaseClient
{
    return await Task.Run(() =>
    {
        try
        {
            var socket = new TSocketTransport(host, port, null);
            var transport = new TFramedTransport(socket);
            var protocol = new TBinaryProtocol(transport);
            var type = typeof(T);
            var client = type.CreateInstance<T>(protocol);
            return client;
        }
        catch (Exception ex)
        {
            logger.Error(ex);
            return default;
        }
    });
}

经过定位发现问题出在下面这行代码:

var socket = new TSocketTransport(host, port, null);

进一步查看 TSocketTransport 源码发现,thrift 内部会调用 Dns.GetHostEntry(host) 解析域名:

public TSocketTransport(string host, int port, TConfiguration config, int timeout = 0)
            : base(config)
{
    try
    {
        var entry = Dns.GetHostEntry(host);
        if (entry.AddressList.Length == 0)
            throw new TTransportException(TTransportException.ExceptionType.Unknown, "unable to resolve host name");

        Host = entry.AddressList[0];
        Port = port;

        TcpClient = new TcpClient(host, port);
        TcpClient.ReceiveTimeout = TcpClient.SendTimeout = timeout;
        TcpClient.Client.NoDelay = true;
        SetInputOutputStream();
    }
    catch (SocketException e)
    {
        throw new TTransportException(TTransportException.ExceptionType.Unknown, e.Message, e);
    }
}

问题就出在这里,我传的 host 是 IP 地址,但这个构造函数期望的 host 显然是个域名,而我的使用环境在局域网,因此解析这个域名就会很慢。

解决办法很简单,调用另外一个构造函数即可:

public TSocketTransport(IPAddress host, int port, TConfiguration config, int timeout = 0)

参考资料