简体   繁体   English

Windows上的DNS反向查询会阻塞几秒钟,以获取无法解析的IP地址

[英]Rerverse dns lookups on Windows block for several seconds for unresolvable IP addresses

I'm using Java's InetAddress.getHostName() to perform some reverse DNS lookups, and something seems wrong with the time it takes. 我正在使用Java的InetAddress.getHostName()进行一些反向DNS查找,并且花费的时间似乎有些问题。 Here's a code snippet: 这是一个代码片段:

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));
    }
}

And here's the output on my machine: 这是我机器上的输出:

    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

Resolving both 10.0.0.138 and 216.239.49.245 takes 4.5 seconds each, regardless of the number of times I've ran this code. 不管我运行这段代码的次数如何,解析10.0.0.138和216.239.49.245都需要4.5秒。 This seems to happen with all unresolvable IP addresses. 所有无法解析的IP地址似乎都发生了这种情况。

This isn't a networking issue since according to a wireshark capture, DNS queries aren't even sent when this code is run unless the DNS cache is cleared first (and then the results are even slower - around 4.7 seconds per resolution). 这不是网络问题,因为根据Wireshark捕获, 除非先清除DNS缓存,否则 甚至在运行此代码时都不会发送 DNS查询(然后结果甚至更慢-每个分辨率大约4.7秒)。

So does it actually take Java 4.5 seconds to timeout against the OS's local DNS cache? 那么,针对操作系统的本地DNS缓存超时实际上需要Java 4.5秒吗? That makes no sense. 这是没有意义的。 The command line utility nslookup returns (unresolvable) results for these IP addresses much faster, and it doesn't even use the cache! 命令行实用程序nslookup更快地返回这些IP地址的结果(无法解析),它甚至不使用缓存!

Can some one explain this behavior and suggest way to speed up these resolutions? 有人可以解释这种现象并提出加快这些解决方案的方法吗? The only thing I can think of without turning to external libraries is using multiple threads so at least the 4.5 second timeout will be executed in parallel. 我唯一想到的不用外部库就是使用多个线程,因此至少4.5秒的超时将并行执行。

For reference, I'm using JDK 7u71 on Windows 7 x64 作为参考,我在Windows 7 x64上使用JDK 7u71

Edit1 : This question seems relevant, but the answer there says that the performance depends on the network, which is not what I observed. Edit1这个问题似乎相关,但是那里的答案表明性能取决于网络,这不是我观察到的。

Edit2: 编辑2:

This seems to be a windows issue. 这似乎是Windows问题。 A machine in the same LAN, that uses the exact same DNS, running OpenSuse 13.1 with JDK 1.7u67 returned the following results: 在同一LAN中使用完全相同的DNS并在JDK 1.7u67上运行OpenSuse 13.1的计算机返回以下结果:

Without DNS caching: 没有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

With DNS caching: 使用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: 编辑3:

Eventually I had to work around the issue by doing my own reverse DNS lookups using dnsjava . 最终,我不得不通过使用dnsjava进行自己的反向DNS查找来解决此问题。

It looks like an issue with the implementation of the DNS client in Windows. Windows中的DNS客户端实现似乎有问题。 I just tried the same logic in C#.NET: 我只是在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();
    }

these are results: 这些是结果:

   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

The interesting part is that after a DNS cache flush, Windows sends all DNS requests to the network. 有趣的是,在刷新DNS缓存后,Windows将所有DNS请求发送到网络。 The DNS server replies after 0.25 second but if the answer is "No Such Name", the DNS client still blocks for the entire duration of the timeout. DNS服务器在0.25秒后回复,但如果回答是“ No Such Name”,则DNS客户端在整个超时时间内仍会阻塞。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM