反向DNS在Windows上查找阻止几秒钟的无法parsing的IP地址

我正在使用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 

无论运行此代码的次数是多less,parsing10.0.0.138和216.239.49.245都需要4.5秒。 这似乎与所有无法parsing的IP地址发生。

这不是一个networking问题,因为根据wireshark捕获,当运行这个代码时,DNS查询甚至不会被发送除非DNScaching被首先清除 (然后结果更慢 – 每个分辨率大约4.7秒)。

那么实际上是否需要4.5秒的时间来处理操作系统的本地DNScaching呢? 这是没有意义的。 命令行实用程序nslookup更快地返回(无法parsing)这些IP地址的结果,甚至不使用caching!

有人可以解释这种行为,并build议加快这些决议的方式? 我能想到的唯一不用转向外部库的就是使用multithreading,所以至less4.5秒的超时将被并行执行。

作为参考,我在Windows 7 x64上使用JDK 7u71

编辑1 : 这个问题似乎是相关的,但那里的答案说,性能取决于networking,这不是我所观察到的。

EDIT2:

这似乎是一个Windows问题。 同一局域网中的一台机器,使用完全相同的DNS,运行带有JDK 1.7u67的OpenSuse 13.1,返回以下结果:

没有DNScaching:

 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 

使用DNScaching:

 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查找来解决这个问题。

这看起来像在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秒后回复,但如果答案是“没有这样的名字”,则DNS客户端在整个超时期间仍然阻塞。