Java内部DNS查询实现和参数设置

一、Java内部DNS查询

Java使用域名查询时,用的自己内部的域名实现机制,最后都是交给InetAddress去做DNS解析。

源码分析参考:

//域名查询 String dottedQuadIpAddress = InetAddress.getByName( "blog.arganzheng.me" ).getHostAddress(); //IP对应域名 InetAddress[] addresses = InetAddress.getAllByName("8.8.8.8"); // ip or DNS name for (int i = 0; i < addresses.length; i++) { String hostname = addresses[i].getHostName(); System.out.println(hostname); } 

二、JNDI DNS服务提供者设置(JNDI DNS service provider settings)

Oracle.com/javase/7/docs/technotes/guides/net/properties.html

sun.net.spi.nameservice.provider.<n>=<default|dns,sun|...>Specifies the name service provider that you can use. By default, Java will use the system configured name lookup mechanism, such as file, nis, etc. You can specify your own by setting this option. <n> takes the value of a positive number, it indicates the precedence order with a small number takes higher precendence over a bigger number. Aside from the default provider, the JDK includes a DNS provider named "dns,sun".

Prior to JDK 7, the first provider that was successfully loaded was used. In JDK 7, providers are chained, which means that if a lookup on a provider fails, the next provider in the list is consulted to resolve the name.

重点是这个参数,区分jdk版本,jdk7之前,只有第一个设置的provier生效;jdk7及其之后,provider链都生效,从第一个开始,指导解析成功。

Java有两个实现:

  Default:相当于设置System.setProperty("sun.net.spi.nameservice.provider.1", "default"); 具体解析过程是系统调用,依赖系统的DNS解析方式。

    linux 默认的DNS方式是读取/etc/resolv.conf进行DNS解析。

    mac 默认的方式是向网关请求获取DNS服务器,然后直接请求DNS服务器进行解析,没有读取/etc/resolv.conf。

  <dns,sun>:System.setProperty("sun.net.spi.nameservice.provider.1", "dns,sun");读取/etc/resolv.conf进行DNS解析。

sun.net.spi.nameservice.nameservers=<server1_ipaddr,server2_ipaddr ...>You can specify a comma separated list of IP addresses that point to the DNS servers you want to use. If the sun.net.spi.nameservice.nameservers property is not defined, then the provider will use any name servers already configured in the platform DNS configuration.

sun.net.spi.nameservice.domain=<domainname>This property specifies the default DNS domain name, for instance, eng.example.com. If the sun.net.spi.nameservice.domain property is not defined then the provider will use any domain or domain search list configured in the platform DNS configuration.

使用dnsjava的provider:

1. 工程添加dnsjava包。

2. 设置provider:System.setProperty("sun.net.spi.nameservice.provider.1","dns,dnsjava");

dnsjava的provider功能强大:

There's no standard way to determine what the local nameserver or DNS search path is at runtime from within the JVM. dnsjava attempts several methods until one succeeds. - The properties 'dns.server' and 'dns.search' (comma delimited lists) are checked. The servers can either be IP addresses or hostnames (which are resolved using Java's built in DNS support). - The sun.net.dns.ResolverConfiguration class is queried. - On Unix, /etc/resolv.conf is parsed. - On Windows, ipconfig/winipcfg is called and its output parsed. This may fail for non-English versions on Windows. - As a last resort, "localhost" is used as the nameserver, and the search path is empty.

参考:

三、JVM DNS缓存

如果启动了security manager,则永久缓存,但一般情况下大家是不会去启动security manager的。

可以再程序里面设置不缓存,或者在启动参数里面设置

java.security.Security.setProperty("networkaddress.cache.ttl" , "0")

如果没有启动security manager,则要区分JDK版本:

1.5及其一下,java对DNS解析IP进行缓存,默认缓存超时时间为-1(在重启JVM前永久缓存)

1.6及其以上,缓存时间根据ttl。

参考:

设置ttl:在命令启动JVM的时候设置参数"-Dnetworkaddress.cache.ttl=60 -Dsun.net.inetaddr.ttl=60"

四、Linux服务器是否会对dns缓存,ttl是否有用?

linux本身是没有dns缓存的,想使用dns缓存的话需要自己安装一个服务程序NSCD.

$ ps aux | grep nscd 可以查看

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/294b6a086b5f8c84ede0247ba0ac8236.html