jvm中的dns缓存使用

当前版本 jdk8

参数配置

google后发现可通过networkaddress.cache.ttlsun.net.inetaddr.ttl参数进行jvm级别的配置。

查寻jdk源码,相关代码都存放于

1
InetAddressCachePolicy

其主要逻辑位于static代码块中

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
 // Controls the cache policy for successful lookups only
private static final String cachePolicyProp = "networkaddress.cache.ttl";
private static final String cachePolicyPropFallback =
"sun.net.inetaddr.ttl";

// Controls the cache policy for negative lookups only
private static final String negativeCachePolicyProp =
"networkaddress.cache.negative.ttl";
private static final String negativeCachePolicyPropFallback =
"sun.net.inetaddr.negative.ttl";

public static final int DEFAULT_POSITIVE = 30;

static {
Integer tmp = null;

try {
tmp = new Integer(
java.security.AccessController.doPrivileged (
new PrivilegedAction<String>() {
public String run() {
return Security.getProperty(cachePolicyProp);
}
}));
} catch (NumberFormatException e) {
// ignore
}
if (tmp != null) {
cachePolicy = tmp.intValue();
if (cachePolicy < 0) {
cachePolicy = FOREVER;
}
propertySet = true;
} else {
tmp = java.security.AccessController.doPrivileged
(new sun.security.action.GetIntegerAction(cachePolicyPropFallback));
if (tmp != null) {
cachePolicy = tmp.intValue();
if (cachePolicy < 0) {
cachePolicy = FOREVER;
}
propertySet = true;
} else {
/* No properties defined for positive caching. If there is no
* security manager then use the default positive cache value.
*/
if (System.getSecurityManager() == null) {
cachePolicy = DEFAULT_POSITIVE;
}
}
}

try {
tmp = new Integer(
java.security.AccessController.doPrivileged (
new PrivilegedAction<String>() {
public String run() {
return Security.getProperty(negativeCachePolicyProp);
}
}));
} catch (NumberFormatException e) {
// ignore
}

if (tmp != null) {
negativeCachePolicy = tmp.intValue();
if (negativeCachePolicy < 0) {
negativeCachePolicy = FOREVER;
}
propertyNegativeSet = true;
} else {
tmp = java.security.AccessController.doPrivileged
(new sun.security.action.GetIntegerAction(negativeCachePolicyPropFallback));
if (tmp != null) {
negativeCachePolicy = tmp.intValue();
if (negativeCachePolicy < 0) {
negativeCachePolicy = FOREVER;
}
propertyNegativeSet = true;
}
}
}

通过上述代码,可以很清楚的看到networkaddress.cache.ttl配置优先级最高,取不到的情况下取sun.net.inetaddr.ttl配置;
若都无配置且SecurityManager(jdk17过时)为空的情况下,那么就执行配置设置(默认为30s)。

使用方式

通过名字,很明显的看到这是网络地址缓存策略类,其使用场景位于InetAddress类中

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
private static InetAddress[] getAllByName0 (String host, InetAddress reqAddr, boolean check)
throws UnknownHostException {

/* If it gets here it is presumed to be a hostname */
/* Cache.get can return: null, unknownAddress, or InetAddress[] */

/* make sure the connection to the host is allowed, before we
* give out a hostname
*/
if (check) {
SecurityManager security = System.getSecurityManager();
if (security != null) {
security.checkConnect(host, -1);
}
}

InetAddress[] addresses = getCachedAddresses(host);

/* If no entry in cache, then do the host lookup */
if (addresses == null) {
addresses = getAddressesFromNameService(host, reqAddr);
}

if (addresses == unknown_array)
throw new UnknownHostException(host);

return addresses.clone();
}

getAllByName0方法中首先尝试从本地缓存中获取参数host对应的ip地址信息;
当缓存为空的情况,执行不同nameSpace的lookupAllHostAddr方法查找,例如ipv4类型由Inet4AddressImpl提供native方法。

测试

1
2
3
4
5
6
7
8
9
10
ExecutorService executor = Executors.newScheduledThreadPool(1);
executor.sheduledAtFixedRate(() -> {
InetAddress address = null;
try {
address = InetAddress.getByName("tuean.cn");
logger.info(address.getHostAddress);
} catch (Exception var) {
logger.error("解析失败");
}
}, 1, 1, TimeUnit.SECONDS);

上述代码启动后即以每秒一次的速度打印tuean.cn对应的ip。

附录

1. cache reference guide
2. jdk source code