我们在沙盒 Java Applet 中遇到了问题,因为 SecurityManager 执行反向 DNS 查找。见其他问题。
但根本问题是,反向 DNS 查找大约需要 4.5 秒(没有域结果)。问题不是丢失的结果(在这种情况下它会返回 IP),而只是它需要很长时间的事实。
该问题也与 SecurityManager 无关,它只是在那里成为问题,因为 Permissions 类在遇到此问题时持有锁,因此将许多其他线程冻结 4.5(或更多)秒。
还有一些没有域名结果(即返回 IP)的域不需要 4.5 秒。例如“staminus.net”。
SSCCE:
String host = "random.org";
// "random.org" - IP result, takes 4.5 seconds
// "cdn.knuddelscom.de" - IP result, takes 4.5 seconds
// "staminus.net" - IP result, fast
// "google.com" - domain result: fra15s11-in-f14.1e100.net, fast
InetAddress addr = Inet4Address.getByName(host);
for (int i = 0; i < 100; i++)
{
long start = System.currentTimeMillis();
String hostName = Inet4Address.getByAddress(addr.getAddress()).getHostName();
long end = System.currentTimeMillis();
System.out.println((i + 1) + " RDNS " + host + " ... (" + (end - start) + "ms): " + hostName);
}
(使用 Java JDK 1.8.0_40 测试)
我使用 Sysinternals Process Explorer 对挂起的线程进行了 Windows API 调用线程转储,但我对此知之甚少,无法判断发生了什么:
ntoskrnl.exe!KeSynchronizeExecution+0x2246
ntoskrnl.exe!KeWaitForMultipleObjects+0x135e
ntoskrnl.exe!KeWaitForMultipleObjects+0xdd9
ntoskrnl.exe!KeWaitForSingleObject+0x373
ntoskrnl.exe!KeReleaseSemaphore+0xd33
ntoskrnl.exe!NtSetEvent+0xf99
ntoskrnl.exe!NtSetEvent+0x447
ntoskrnl.exe!RtlEqualUnicodeString+0x9ae
ntoskrnl.exe!setjmpex+0x34a3
ntdll.dll!ZwAlpcSendWaitReceivePort+0xa
RPCRT4.dll!NDRCContextBinding+0x6c8
RPCRT4.dll!NdrClientCall3+0xded
RPCRT4.dll!NdrClientCall3+0xfe
DNSAPI.dll!AddRefQueryBlobEx+0x753
DNSAPI.dll!DnsValidateName_W+0x1312
DNSAPI.dll!DnsQueryEx+0x103
mswsock.dll!Tcpip4_WSHOpenSocket2+0x1578
mswsock.dll!Tcpip4_WSHOpenSocket2+0x141e
mswsock.dll!Tcpip4_WSHOpenSocket2+0x1252
WS2_32.dll!WSALookupServiceNextW+0x1d8
WS2_32.dll!WSALookupServiceNextW+0xa3
WS2_32.dll!GetHostNameW+0x2e44
WS2_32.dll!GetHostNameW+0x1130
WS2_32.dll!getnameinfo+0xaf
net.dll!Java_java_net_Inet6AddressImpl_getHostByAddr+0x124
因为它总是大约 4.5 秒,所以看起来很像超时。因此,这种解释是合乎逻辑的:(R)DNS 服务器不响应我们的请求。
我们如何测试这个?
我们如何解决这个问题?