Java Dns Cache Manipulator 介绍
Java Dns Cache Manipulator(DCM) Library
通过代码直接设置Java的DNS(实际上设置的是DNS Cache),支持JDK 6+,支持IPv6。
[](https://github.com/alibaba/java-dns-cache-
manipulator/tree/master/library#Wrench-功能)功能
设置/重置DNS(不会再去Lookup DNS)
可以设置单条
或是通过Properties文件批量设置
清空DNS Cache(即所有的域名重新Lookup DNS)
删除一条DNS Cache(即重新Lookup DNS)
查看DNS Cache内容
修改/查看JVM缺省的DNS的缓存时间
[](https://github.com/alibaba/java-dns-cache-
manipulator/tree/master/library#art-需求场景)需求场景
单元测试需要每个开发都在开发机上做host绑定,增加了依赖的配置操作且繁琐重复。
一些功能需要域名作为输入参数,如使用HTTP请求的网关 或是 有域名检查限制的Web应用。
这种情况下,让需要让一个域名连接到测试机器的IP上,或是 使用一个还不存在的域名但又不想或不能去配置DNS。在性能测试时,
一个JVM进程可以对应一套域名绑定,相互之间不影响,可以实现多场景,多域名绑定的需求压测。
打开Java中的SecurityManager时(如在Web容器Tomcat中的Web应用),Java的DNS缺省是不会失效的。 如果域名绑定的IP变了,可以通过这个库重置DNS,作为一个临时的手段( 强烈不推荐 )。
通过Java Dns Cache Manipulator Tool修改运行中JVM DNS Cache。
无需 应用包含了Java Dns Cache Manipulator Library依赖(即Jar)。或通过执行入口调用Java Dns Cache Manipulator Library的方法,比如远程调用或是jvm-ssh-groovy-shell。
需要 应用已经包含了Java Dns Cache Manipulator Library依赖(即Jar)。
[](https://github.com/alibaba/java-dns-cache-
manipulator/tree/master/library#busts_in_silhouette-user-guide)User Guide
通过类DnsCacheManipulator设置DNS。
[](https://github.com/alibaba/java-dns-cache-
manipulator/tree/master/library#直接设置)直接设置
DnsCacheManipulator.setDnsCache(www.hello.com, 192.168.1.1); DnsCacheManipulator.setDnsCache(www.world.com, 1234:5678:0:0:0:0:0:200e); // 支持IPv6地址 // 之后Java代码中使用到域名都会解析成上面指定的IP。 // 下面是一个简单获取域名对应的IP,演示一下: String ip = InetAddress.getByName(www.hello.com).getHostAddress(); // ip = 192.168.1.1 String ipv6 = InetAddress.getByName(www.world.com).getHostAddress(); // ipv6 = 1234:5678:0:0:0:0:0:200e
[](https://github.com/alibaba/java-dns-cache-
manipulator/tree/master/library#通过dns-cacheproperties文件批量配置)通过dns-
cache.properties文件批量配置
使用方式如下:
在Classpath上,提供文件dns-cache.properties:
# 配置格式: # <host> = <ip> www.hello-world.com=192.168.1.1 www.foo.com=192.168.1.2
然后通过下面的一行代码完成批量设置:
DnsCacheManipulator.loadDnsCacheConfig();
在单元测试中,往往会写在测试类的setUp方法中,如:
@BeforeClass public static void beforeClass() throws Exception { DnsCacheManipulator.loadDnsCacheConfig(); }
[](https://github.com/alibaba/java-dns-cache-
manipulator/tree/master/library#清空jvm-dns-cache)清空JVM DNS Cache
DnsCacheManipulator.clearDnsCache();
[](https://github.com/alibaba/java-dns-cache-
manipulator/tree/master/library#删除一条dns-cache)删除一条DNS Cache
即重新Lookup DNS。
DnsCacheManipulator.removednsCache(baidu.com);
[](https://github.com/alibaba/java-dns-cache-
manipulator/tree/master/library#查看jvm-dns-cache)查看JVM DNS Cache
DnsCache dnsCache = DnsCacheManipulator.getWholednsCache() System.out.println(dnsCache);
[](https://github.com/alibaba/java-dns-cache-
manipulator/tree/master/library#修改查看jvm缺省的dns的缓存时间)修改/查看JVM缺省的DNS的缓存时间
// 查看缓存时间,单位秒。-1表示永远缓存,0表示不缓存 int cachePolicy = DnsCacheManipulator.getDnsCachePolicy(); // 设置缓存时间 DnsCacheManipulator.setDnsCachePolicy(2); // 查看未命中条目的缓存时间 DnsCacheManipulator.getDnsNegativeCachePolicy() // 设置未命中条目的缓存时间 DnsCacheManipulator.setDnsNegativeCachePolicy(0);
[](https://github.com/alibaba/java-dns-cache-
manipulator/tree/master/library#使用注意)使用注意
域名不区分大小写,域名会统一转成小写,再进入DNS Cache。
其中一个引发的现象是,DNS查询结果的域名会和输入的域名大小写不同,如果输入的域名有大写字母。对于已经完成解析保存了IP的逻辑,修改JVM DNS缓存,不会生效!可以重新创建 连接或Client解决。
如对于HttpClient:HttpClient client = new HttpClient();
getmethod m1 = new getmethod(http://www.baidu.com”);
client.executeMethod(m1);
String content = m1.getResponseBodyAsstring(); // 修改DNS,绑定到自己的机器
DnsCacheManipulator.setDnsCache(www.baidu.com”, “192.168.1.1”); // 重新执行m1,仍然是老结果
client.executeMethod(m1);
String content = m1.getResponseBodyAsstring(); // 重新创建getmethod,才能得到自己机器上的结果
getmethod m2 = new getmethod(http://www.baidu.com”);
client.executeMethod(m2);
content = m2.getResponseBodyAsstring();
[](https://github.com/alibaba/java-dns-cache-
manipulator/tree/master/library#更多详细功能)更多详细功能
参见类[DnsCacheManipulator](https://github.com/alibaba/java-dns-cache-
manipulator/blob/master/library/src/main/java/com/alibaba/dcm/DnsCacheManipulator.java)的文档说明。
[](https://github.com/alibaba/java-dns-cache-
manipulator/tree/master/library#经过测试的jdk)经过测试的JDK
JDK | 系统 | On | 备注 |
---|---|---|---|
openjdk6 64-Bit | Linux | travis-ci | |
oraclejdk7 64-Bit | Linux | travis-ci | |
openjdk7 64-Bit | Linux | travis-ci | |
oraclejdk8 64-Bit | Linux | travis-ci | |
applejdk6 64-Bit | Mac | 个人Mac | [jdk6及以下,Apple提供了自己的Java版本](https://java.com/zh_CN/download/faq/java_mac.xml)。 |
oraclejdk7 64-Bit | Mac | 个人Mac | 从jdk7开始,Mac jdk直接在Oracle下载。 |
oraclejdk8 64-Bit | Mac | 个人Mac | |
oraclejdk7 64-Bit | windows server 2012 r2 | appveyor | |
oraclejdk7 32-Bit | windows server 2012 r2 | appveyor | |
oraclejdk8 64-Bit | windows server 2012 r2 | appveyor | |
oraclejdk8 32-Bit | windows server 2012 r2 | appveyor |
PS:感谢 travis-ci 和
appveyor 免费提供了持续集成环境。
Java API Docs
Java api文档地址: http://alibaba.github.io/java-dns-cache-manipulator/apidocs
[](https://github.com/alibaba/java-dns-cache-
manipulator/tree/master/library#cookie-依赖)依赖
Maven示例:
<dependency> <groupId>com.alibaba</groupId> <artifactId>dns-cache-manipulator</artifactId> <version>1.5.0</version> </dependency>
可以在search.maven.org查看最新的版本。
[](https://github.com/alibaba/java-dns-cache-
manipulator/tree/master/library#mortar_board-developer-guide)Developer Guide
[](https://github.com/alibaba/java-dns-cache-
manipulator/tree/master/library#如何修改jvm的dns-cache)如何修改JVM的DNS Cache
JVM的DNS Cache维护在类InetAddress的addressCache私有字段中,通过反射来修改,
具体参见InetAddressCacheUtil。
[](https://github.com/alibaba/java-dns-cache-
manipulator/tree/master/library#注意修改jvm的dns-cache的线程安全问题)注意修改JVM的DNS
Cache的线程安全问题
JVM的DNS Cache显然是全局共用的,所以修改需要同步以保证没有并发问题。
通过查看类InetAddress的实现可以确定:通过以addressCache字段为锁的synchronized块来保证线程安全。
其中关键代码(JDK 7)如下:
/* * Cache the given hostname and addresses. */ private static void cacheAddresses(String hostname, InetAddress[] addresses, boolean success) { hostname = hostname.toLowerCase(); synchronized (addressCache) { cacheInitIfNeeded(); if (success) { addressCache.put(hostname, addresses); } else { negativeCache.put(hostname, addresses); } } }
InetAddressCacheUtil类中对DNS
Cache的读写也一致地加了以addressCache为锁的synchronized块,以保证线程安全。
[](https://github.com/alibaba/java-dns-cache-
manipulator/tree/master/library#需要测试不同版本jdk)需要测试不同版本JDK
本库实现使用了JDK的非公开API,不同JDK实现会不一样,即需要有兼容逻辑,并对不同版本JDK进行测试,以保证功能。
目前测试包含JDK版本参见【经过测试的JDK】一节。
相关资料
tanhaichao的javahost项目, 该项目的使用文档。
本项目如何设置Java DNS Cache的解法来自该项目。刚开始在持续集成项目中碰到host绑定的问题时,也是使用该项目来解决的类InetAddress的源代码:
JDK 6的InetAddress
JDK 7的InetAddress
JDK 8的InetAddress
java dns解析缓存之源码解析,写得很完整,源码解析。给出值得注意的结论:
打开Java中的SecurityManager,DNS缓存将不会失效。
否则,可访问的DNS解析缺省缓存30秒,不可访问的DNS解析缺省缓存10秒。
关于jvm dns cache(域名缓存时间),给出“对于多条A记录是采用什么策略返回IP”的结论:
在缓存有效期内,取到的IP永远是缓存中全部A记录的第一条,并没有轮循之类的策略。
缓存失效之后重新进行DNS解析,因为每次域名解析返回的A记录顺序会发生变化(dig www.google.com测试可见),所以缓存中的数据顺序也变了,取到的IP也变化。
通过JAVA反射修改JDK 1.6当中DNS缓存内容,给出了修改DNS缓存在性能测试下使用的场景。
java InetAddress 的dns cache问题, 说明HttpClient需要重新创建getmethod/PostMethod对象以使设置DNS生效问题。
Java DNS FAQ
Java Dns Cache Manipulator 官网
https://github.com/alibaba/java-dns-cache-manipulator
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。