我正在使用Java InetAddress.getHostName()来执行一些反向DNS查找,并且花费的时间似乎有些问题。这是一个代码片段:
InetAddress.getHostName()
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地址似乎都发生了这种情况。
这不是网络问题,因为根据Wireshark捕获, 除非先清除DNS缓存,否则* 甚至 在运行此代码时 都不会发送 DNS查询(然后结果甚至更慢-每个分辨率大约4.7秒)。 *
那么,针对操作系统的本地DNS缓存超时实际上需要Java 4.5秒吗?这是没有意义的。命令行实用程序nslookup以更快的速度返回这些IP地址的结果(无法解析),它甚至不使用缓存!
nslookup
有人可以解释这种现象并提出加快这些解决方案的方法吗?我唯一想到的不用外部库就是使用多个线程,因此至少4.5秒的超时将并行执行。
供参考,我在Windows 7 x64上使用JDK 7u71
编辑:
这似乎是Windows问题。在同一LAN中使用完全相同的DNS并在JDK 1.7u67上运行OpenSuse 13.1的计算机返回以下结果:
没有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
编辑3:
最终,我不得不通过使用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秒后回复,但如果回答是“ No Such Name”,则DNS客户端在整个超时时间内仍会阻塞。