Windows 上的反向 dns 查找会阻塞几秒钟以获取无法解析的 IP 地址
我正在使用 Java 的 InetAddress.getHostName()
执行一些反向 DNS 查找,但它所花费的时间似乎有问题.这是一个代码片段:
I'm using Java's InetAddress.getHostName()
to perform some reverse DNS lookups, and something seems wrong with the time it takes. 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
", 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 地址上.
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. This seems to happen with all unresolvable IP addresses.
这不是网络问题,因为根据 wireshark 的捕获,运行此代码时,DNS 查询甚至不会发送除非首先清除 DNS 缓存(然后结果甚至更慢 - 每个分辨率大约 4.7 秒).
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).
那么,Java 是否真的需要 4.5 秒才能针对操作系统的本地 DNS 缓存超时?这是没有意义的.命令行实用程序 nslookup
更快地返回(无法解析)这些 IP 地址的结果,甚至不使用缓存!
So does it actually take Java 4.5 seconds to timeout against the OS's local DNS cache? 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!
有人可以解释这种行为并提出加快这些解决方案的方法吗?在不求助于外部库的情况下,我唯一能想到的就是使用多个线程,因此至少 4.5 秒的超时将并行执行.
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.
作为参考,我在 Windows 7 x64 上使用 JDK 7u71
For reference, I'm using JDK 7u71 on Windows 7 x64
编辑1:这个问题似乎相关,但答案那里说性能取决于网络,这不是我观察到的.
Edit1: This question seems relevant, but the answer there says that the performance depends on the network, which is not what I observed.
这似乎是一个 Windows 问题.同一 LAN 中的机器使用完全相同的 DNS,运行带有 JDK 1.7u67 的 OpenSuse 13.1 返回以下结果:
This seems to be a windows issue. A machine in the same LAN, that uses the exact same DNS, running OpenSuse 13.1 with JDK 1.7u67 returned the following results:
没有 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
最终我不得不使用 dnsjava 进行自己的反向 DNS 查找来解决这个问题.
Eventually I had to work around the issue by doing my own reverse DNS lookups using dnsjava.
推荐答案
看来是 Windows 中 DNS 客户端的实现有问题.我刚刚在 C#.NET 中尝试了相同的逻辑:
It looks like an issue with the implementation of the DNS client in Windows. I just tried the same logic in 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 客户端仍然会在整个超时期间阻塞.
The interesting part is that after a DNS cache flush, Windows sends all DNS requests to the network. 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.
相关文章