๐ A tiny 0-dependency thread-safe Javaโข lib for setting/viewing dns programmatically without touching host file, make unit/integration testing portable; and a tiny tool for setting/viewing dns of running JVM process.
APACHE-2.0 License
๐ English Documentation | ๐ ไธญๆๆๆกฃ
Java Dns Cache Manipulator(DCM
) contains 2 subprojects:
DCM
LibraryJava 8~21
, support IPv6
.DCM
Tool[!NOTE] Start from
DCM 1.7+
upgrade toJava 8
๐ If you needJava 6
support, use version1.6.x
DCM
) Library
DCM
) LibraryDNS record
Properties
fileJVM
(positive dns cache and negative dns cache)host file
binding to do the test(e.g. unit test, integration test). Turn out:
host file
on the continuous integration machine, which leads to the continuous integration fail.
JVM
process can have a set of domain name binding without affecting other JVM, be able to run stress testing with multi-scenario and multi-domain binding.SecurityManager
in Java
(such as a web application in the Web container Tomcat
), Java
's DNS will not be expired by default. If the IP bound to the domain name changes, you can reset the DNS through this library.
DCM
Tool.DCM
Library dependency (i.e. Jar
).DCM
Library through the execution entry, such as remote call or jvm-ssh-groovy-shell
.DCM
Library dependency (ie Jar
).Set/View DNS through the class DnsCacheManipulator
.
DnsCacheManipulator.setDnsCache("hello.com", "192.168.1.1");
// support IPv6
DnsCacheManipulator.setDnsCache("world.com", "1234:5678:0:0:0:0:0:200e");
// The above settings take effect globally,
// and then all the domain name resolution logic in Java will be the IP set above.
// Let's use a simple method to get the IP of the domain name to demonstrate:
String ip = InetAddress.getByName("hello.com").getHostAddress();
// ip = "192.168.1.1"
String ipv6 = InetAddress.getByName("world.com").getHostAddress();
// ipv6 = "1234:5678:0:0:0:0:0:200e"
// set multiple IPs
DnsCacheManipulator.setDnsCache("hello-world.com", "192.168.2.1", "192.168.2.2");
String ipHw = InetAddress.getByName("hello-world.com").getHostAddress();
// ipHw = 192.168.2.1, read the first IP
InetAddress[] allIps = InetAddress.getAllByName("hello-world.com");
// Read the multiple IP setting
// Set the expiration time, unit is milliseconds
DnsCacheManipulator.setDnsCache(3600 * 1000, "hello-hell.com", "192.168.1.1", "192.168.1.2");
dns-cache.properties
fileIn testing, it is expected that the domain name binding will be written in a configuration file.
The usage is as follows:
provide the file dns-cache.properties
on ClassPath:
# Configuration format:
# <host> = <ip>
hello-world.com=192.168.1.1
# Support setting multiple IPs, separated by commas
foo.com=192.168.1.2,192.168.1.3
# Support IPv6
bar.com=1234:5678:0:0:0:0:0:200e
Then complete the batch setting with the following code:
DnsCacheManipulator.loadDnsCacheConfig();
NOTE:
The default configuration file name is
dns-cache.properties
. and the configuration file name used can be modified through the-D
optiondcm.config.filename
of theJVM
:-Ddcm.config.filename=my-dns-cache.properties
.
// or load the batch setting from the specified file name explicitly
DnsCacheManipulator.loadDnsCacheConfig("my-dns-cache.properties");
In unit testing, it is often written in the setUp
method of the test class, such as:
@BeforeClass
public static void beforeClass() throws Exception {
DnsCacheManipulator.loadDnsCacheConfig();
}
// Get a dns cache entry by host
DnsCacheEntry entry = DnsCacheManipulator.getDnsCache("bing.com");
// get whole dns cache info DnsCache including cache and negative cache.
DnsCache dnsCache = DnsCacheManipulator.getWholeDnsCache();
// get positive dns cache entries
// same as DnsCacheManipulator.getWholeDnsCache().getCache()
List<DnsCacheEntry> positiveEntries = DnsCacheManipulator.getWholeDnsCache();
// get dns negative cache entries
// same as DnsCacheManipulator.getWholeDnsCache().getNegativeCache()
List<DnsCacheEntry> positiveEntries = DnsCacheManipulator.getWholeDnsCache();
aka. relookup DNS later.
DnsCacheManipulator.removeDnsCache("bing.com");
DnsCacheManipulator.clearDnsCache();
// View the cache time, in seconds. -1 means cache forever, 0 means never cache
int cachePolicy = DnsCacheManipulator.getDnsCachePolicy();
// Set the cache time
DnsCacheManipulator.setDnsCachePolicy(2);
// View the cache time of missed entries(negative entries)
DnsCacheManipulator.getDnsNegativeCachePolicy();
// Set the cache time of missed entries
DnsCacheManipulator.setDnsNegativeCachePolicy(0);
With the release of Java 16 the access control of the new Jigsaw module system is starting to be enforced by the JVM. If you use DCM
under Java 16+, add below Java options:
--add-opens java.base/java.net=ALL-UNNAMED
--add-opens java.base/sun.net=ALL-UNNAMED
If you use maven
(e.g. running test), add below config:
<profiles>
<profile>
<id>add-java-open-options-for-jdk16+</id>
<activation>
<jdk>[16,)</jdk>
</activation>
<properties>
<argLine>
--add-opens java.base/java.net=ALL-UNNAMED
--add-opens java.base/sun.net=ALL-UNNAMED
</argLine>
</properties>
</profile>
</profiles>
The domain name is not case-sensitive.
The domain name may be converted to lower case uniformly before entering the JVM
DNS Cache.
One of the causes is that the case of the domain name in the DNS query result will be different from the case of the entered domain name, if the entered domain name has uppercase letters.
For HttpClient
:
HttpClient client = new HttpClient();
GetMethod m1 = new GetMethod("https://bing.com");
client.executeMethod(m1);
String content = m1.getResponseBodyAsString();
// Set up DNS and bind to your own machine
DnsCacheManipulator.setDnsCache("bing.com", "192.168.1.1");
// Re-execute m1, still the old result
client.executeMethod(m1);
String content = m1.getResponseBodyAsString();
// Re-create GetMethod to get the results on your own machine
GetMethod m2 = new GetMethod("https://bing.com");
client.executeMethod(m2);
content = m2.getResponseBodyAsString();
See the documentation for the class DnsCacheManipulator
.
Java API document: http://alibaba.github.io/java-dns-cache-manipulator/apidocs
Maven
example:
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>dns-cache-manipulator</artifactId>
<version>1.8.3</version>
</dependency>
You can view the latest version at search.maven.org.
java dns
่งฃๆ็ผๅญไนๆบ็ ่งฃๆ is very complete and have source code analysis, give noteworthy conclusions:
jvm dns cache
(ๅๅ็ผๅญๆถ้ด), the conclusion of "what strategy is used to return IP for multiple A records" is given:
JAVA
ๅๅฐไฟฎๆนJDK 1.6
ๅฝไธญDNS
็ผๅญๅ
ๅฎน, give the scene of setting DNS cache in performance test.HttpClient
needs to recreate the GetMethod
/PostMethod
object to make the DNS setting take effect.JVM
download the file dcm-x.y.z.tar.gz
.
After decompression, run dcm
in the bin
directory.
$ dcm -h
usage: Options
-h,--help show help
-p,--pid <arg> java process id to attach
# For the Java process whose process ID is 12345
# set the domain name foo.com IP to 1.1.1.1
$ dcm -p 12345 set foo.com 1.1.1.1
# For the Java process whose process ID is 12345
# set the domain name bar.com IP to 2.2.2.2 3.3.3.3 (multiple IPs are possible)
$ dcm -p 12345 set bar.com 2.2.2.2 3.3.3.3
View single entry:
# For the Java process whose process ID is 12345,
# obtain the DNS entry information of the domain name bing.com
$ dcm -p 12345 get bing.com
bing.com 220.181.57.217,180.149.132.47,123.125.114.144 2015-06-05T18:56:09.635+0800
# The output format:
# "the domain name" "IP list (there may be multiple IPs)" "expiration time"
View all DNS cache:
$ dcm -p 12345 list
Dns cache:
bar.com 2.2.2.2,3.3.3.3 292278994-08-17T15:12:55.807+0800
bing.com 220.181.57.217,180.149.132.47,123.125.114.144 2015-06-05T19:00:30.514+0800
foo.com 1.1.1.1 292278994-08-17T15:12:55.807+0800
Dns negative cache:
# Output entries containing Cache and Negative Cache.
# The entry is indented 4 spaces.
# In the above example, Negative Cache is empty.
# Remove a DNS
$ dcm -p 12345 rm bing.com
# Clear all DNS Cache
$ dcm -p 12345 clear
JVM
# View the cache time, in seconds.
# -1 means cache forever, 0 means no cache
$ dcm -p 12345 getPolicy
30
# Set cache time
$ dcm --pid 12345 setPolicy 5
# View the cache time of missed entries, in seconds.
# -1 means cache forever, 0 means no cache
$ dcm -p 12345 getNegativePolicy
10
# Set the cache time of missed entries
$ dcm -p 12345 setNegativePolicy 0
$ dcm -p 12345 load /foo/bar/my-cache.properties
To manipulate dns entries at jvm startup, add the following jvm-options:
# Set individual entry
java -javaagent:<path to jar>="set foo.com 1.1.1.1" --add-opens java.base/java.net=ALL-UNNAMED --add-opens java.base/sun.net=ALL-UNNAMED ...
# Load entries from file
java -javaagent:<path to jar>="load my-cache.properties" --add-opens java.base/java.net=ALL-UNNAMED --add-opens java.base/sun.net=ALL-UNNAMED ...