我正在使用Java的InetAddress.getHostName()
来执行一些反向DNS查找,而且它花费的时间似乎有些不对劲。这是一个代码段:
public static void main(String[] args) throws IOException {
byte[][] addresses = new byte[][] { { 10, (byte) 0, (byte) 0, (byte) 138 }
, new byte[] { (byte) 216, (byte) 239, (byte) 49, (byte) 245 }
,{ 8, (byte) 8, (byte) 8, (byte) 8 } };
for (byte[] addr : addresses) {
InetAddress inet = InetAddress.getByAddress(addr);
long before = System.currentTimeMillis();
String hostName = inet.getHostName();
System.out.printf("%20s %40s %5d\n", inet.getHostAddress(), hostName, (System.currentTimeMillis() - before));
}
}
这是我机器上的输出:
10.0.0.138 10.0.0.138 4503
216.239.49.245 216.239.49.245 4591
8.8.8.8 google-public-dns-a.google.com 8
无论我运行此代码的次数如何,解析10.0.0.138和216.239.49.245都需要4.5秒。这似乎发生在所有无法解析的IP地址上。
这不是网络问题,因为根据wirehark捕获,当此代码运行时,DNS查询甚至无法发送,除非首先清除DNS缓存< / strong>(然后结果更慢 - 每个分辨率大约4.7秒)。
那么它实际上需要Java 4.5秒来对操作系统的本地DNS缓存进行超时吗?这是没有意义的。命令行实用程序nslookup
更快地返回(无法解析)这些IP地址的结果,甚至不使用缓存!
有人可以解释这种行为并提出加快这些决议的方法吗?在没有转向外部库的情况下,我唯一能想到的就是使用多个线程,因此至少4.5秒的超时将并行执行。
供参考,我在Windows 7 x64上使用JDK 7u71
EDIT1 : This问题似乎很相关,但那里的答案表明性能取决于网络,这不是我观察到的。
EDIT2:
这似乎是一个Windows问题。同一局域网中使用完全相同的DNS,运行OpenSuse 13.1和JDK 1.7u67的计算机返回以下结果:
没有DNS缓存:
10.0.0.138 10.0.0.138 116
216.239.49.245 216.239.49.245 5098
8.8.8.8 google-public-dns-a.google.com 301
使用DNS缓存:
10.0.0.138 10.0.0.138 5
216.239.49.245 216.239.49.245 9
8.8.8.8 google-public-dns-a.google.com 40
EDIT3:
最终,我不得不使用dnsjava进行自己的反向DNS查找来解决此问题。
答案 0 :(得分:2)
在Windows中实现DNS客户端似乎是一个问题。我刚刚在C#.NET中尝试了相同的逻辑:
static void Main(string[] args)
{
byte[][] addresses = new byte[][] { new byte[] { 10, (byte) 0, (byte) 0, (byte) 138 },
new byte[] { (byte) 216, (byte) 239, (byte) 49, (byte) 245 },
new byte []{ 8, (byte) 8, (byte) 8, (byte) 8 } };
foreach (byte[] addr in addresses)
{
IPAddress inet = new IPAddress(addr);
DateTime before = DateTime.Now;
String hostName = null;
try
{
hostName = System.Net.Dns.GetHostByAddress(inet).HostName;
}
catch { }
finally
{
DateTime after = DateTime.Now;
Console.WriteLine("{0} {1} {2}", inet.ToString(), hostName!=null?hostName:"N/A", after.Subtract(before));
}
}
Console.ReadLine();
}
这些是结果:
10.0.0.138 N/A 00:00:04.5604560
216.239.49.245 N/A 00:00:04.7984798
8.8.8.8 google-public-dns-a.google.com 00:00:00.0060006
有趣的是,在DNS缓存刷新后,Windows会将所有DNS请求发送到网络。 DNS服务器在0.25秒后回复,但如果答案是“No Such Name”,则DNS客户端仍会在整个超时期间阻止。