Windows 上的反向 dns 查找阻止无法解析的 IP 地址几秒钟
Rerverse dns lookups on Windows block for several seconds for unresolvable IP addresses
我正在使用 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 地址上。
这不是网络问题,因为根据 wireshark 捕获,当此代码为 运行 时,DNS 查询 甚至不会发送 除非先清除 DNS 缓存(然后结果会更慢 - 每次解析大约需要 4.7 秒)。
那么 OS 的本地 DNS 缓存实际上需要 Java 4.5 秒才能超时吗?这是没有意义的。这些 IP 地址的命令行实用程序 nslookup
returns(无法解析)结果要快得多,它甚至不使用缓存!
有人可以解释这种行为并提出加快这些分辨率的方法吗?在不求助于外部库的情况下,我唯一能想到的就是使用多线程,因此至少 4.5 秒的超时将并行执行。
作为参考,我在 Windows 7 x64
上使用 JDK 7u71
编辑 1:
This 问题似乎相关,但那里的答案说性能取决于网络,这不是我观察到的。
编辑2:
这似乎是一个 windows 问题。同一 LAN 中的一台机器使用完全相同的 DNS,运行ning 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
编辑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 客户端在整个超时期间仍会阻塞。
我正在使用 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 地址上。
这不是网络问题,因为根据 wireshark 捕获,当此代码为 运行 时,DNS 查询 甚至不会发送 除非先清除 DNS 缓存(然后结果会更慢 - 每次解析大约需要 4.7 秒)。
那么 OS 的本地 DNS 缓存实际上需要 Java 4.5 秒才能超时吗?这是没有意义的。这些 IP 地址的命令行实用程序 nslookup
returns(无法解析)结果要快得多,它甚至不使用缓存!
有人可以解释这种行为并提出加快这些分辨率的方法吗?在不求助于外部库的情况下,我唯一能想到的就是使用多线程,因此至少 4.5 秒的超时将并行执行。
作为参考,我在 Windows 7 x64
上使用 JDK 7u71编辑 1: This 问题似乎相关,但那里的答案说性能取决于网络,这不是我观察到的。
编辑2:
这似乎是一个 windows 问题。同一 LAN 中的一台机器使用完全相同的 DNS,运行ning 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
编辑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 客户端在整个超时期间仍会阻塞。