java dns gslb

¿Alguna forma de hacer que Java respete el tiempo de espera de caché del DNS(TTL)?



gslb (6)

De acuerdo con las docs.oracle.com/javase/7/docs/technotes/guides/net/… sun.net.inetaddr.ttl docs.oracle.com/javase/7/docs/technotes/guides/net/… , sun.net.inetaddr.ttl es una propiedad específica de la implementación de Sun, que "puede no ser compatible en futuras versiones". "la forma preferida es usar la propiedad de seguridad" networkaddress.cache.ttl .

Usamos GSLB para la distribución geográfica y el equilibrio de carga. A cada servicio se le asigna un nombre de dominio fijo. A través de la magia de DNS, el nombre de dominio se resuelve en una IP más cercana al servidor con la menor carga. Para que funcione el equilibrio de carga, el servidor de aplicaciones debe respetar el TTL de la respuesta de DNS y resolver el nombre de dominio nuevamente cuando se agote el tiempo de caché. Sin embargo, no pude encontrar una manera de hacerlo en Java.

La aplicación está en Java 5, ejecutándose en Linux (Centos 5).


Esto obviamente se ha solucionado en versiones más recientes (SE 6 y 7). Experimento un tiempo máximo de caché de 30 segundos cuando ejecuto el siguiente fragmento de código mientras veo la actividad del puerto 53 usando tcpdump.

/** * http://.com/questions/1256556/any-way-to-make-java-honor-the-dns-caching-timeout-ttl * * Result: Java 6 distributed with Ubuntu 12.04 and Java 7 u15 downloaded from Oracle have * an expiry time for dns lookups of approx. 30 seconds. */ import java.util.*; import java.text.*; import java.security.*; import java.net.InetAddress; import java.net.UnknownHostException; import java.io.BufferedReader; import java.io.InputStreamReader; import java.io.InputStream; import java.net.URL; import java.net.URLConnection; public class Test { final static String hostname = "www.google.com"; public static void main(String[] args) { // only required for Java SE 5 and lower: //Security.setProperty("networkaddress.cache.ttl", "30"); System.out.println(Security.getProperty("networkaddress.cache.ttl")); System.out.println(System.getProperty("networkaddress.cache.ttl")); System.out.println(Security.getProperty("networkaddress.cache.negative.ttl")); System.out.println(System.getProperty("networkaddress.cache.negative.ttl")); while(true) { int i = 0; try { makeRequest(); InetAddress inetAddress = InetAddress.getLocalHost(); System.out.println(new Date()); inetAddress = InetAddress.getByName(hostname); displayStuff(hostname, inetAddress); } catch (UnknownHostException e) { e.printStackTrace(); } try { Thread.sleep(5L*1000L); } catch(Exception ex) {} i++; } } public static void displayStuff(String whichHost, InetAddress inetAddress) { System.out.println("Which Host:" + whichHost); System.out.println("Canonical Host Name:" + inetAddress.getCanonicalHostName()); System.out.println("Host Name:" + inetAddress.getHostName()); System.out.println("Host Address:" + inetAddress.getHostAddress()); } public static void makeRequest() { try { URL url = new URL("http://"+hostname+"/"); URLConnection conn = url.openConnection(); conn.connect(); InputStream is = conn.getInputStream(); InputStreamReader ird = new InputStreamReader(is); BufferedReader rd = new BufferedReader(ird); String res; while((res = rd.readLine()) != null) { System.out.println(res); break; } rd.close(); } catch(Exception ex) { ex.printStackTrace(); } } }


Java tiene un comportamiento de almacenamiento en caché de DNS bastante extraño. Su mejor opción es apagar el almacenamiento en caché de DNS o configurarlo en un número bajo como 5 segundos.

networkaddress.cache.ttl (predeterminado: -1)
Indica la política de almacenamiento en caché para búsquedas de nombre exitosas del servicio de nombres. El valor se especifica como entero para indicar el número de segundos para almacenar en caché la búsqueda exitosa. Un valor de -1 indica "caché para siempre".

networkaddress.cache.negative.ttl (predeterminado: 10)
Indica la política de almacenamiento en caché para las búsquedas de nombres no exitosas del servicio de nombres. El valor se especifica como entero para indicar el número de segundos para almacenar en caché el error de las búsquedas no exitosas. Un valor de 0 indica "nunca caché". Un valor de -1 indica "caché para siempre".


Para ampliar la respuesta de Byron, creo que debe editar el archivo java.security en el %JRE_HOME%/lib/security para efectuar este cambio.

Aquí está la sección relevante:

# # The Java-level namelookup cache policy for successful lookups: # # any negative value: caching forever # any positive value: the number of seconds to cache an address for # zero: do not cache # # default value is forever (FOREVER). For security reasons, this # caching is made forever when a security manager is set. When a security # manager is not set, the default behavior is to cache for 30 seconds. # # NOTE: setting this to anything other than the default value can have # serious security implications. Do not set it unless # you are sure you are not exposed to DNS spoofing attack. # #networkaddress.cache.ttl=-1

Documentación en el archivo java.security here .


Para resumir las otras respuestas, en <jre-path>/lib/security/java.security puede establecer el valor de la propiedad networkaddress.cache.ttl para ajustar cómo se almacenan en caché las búsquedas DNS. Tenga en cuenta que esto no es una propiedad del sistema, sino una propiedad de seguridad. Pude configurar esto usando:

java.security.Security.setProperty("networkaddress.cache.ttl", "<value>");

Esto también se puede establecer mediante la propiedad del sistema -Dsun.net.inetaddr.ttl aunque esto no anulará una propiedad de seguridad si está configurada en otro lugar.

También me gustaría agregar que si está viendo este problema con los servicios web en WebSphere, como yo lo estaba, configurar networkaddress.cache.ttl no será suficiente. disableWSAddressCaching establecer la propiedad del sistema disableWSAddressCaching en true . A diferencia de la propiedad time-to-live, esto se puede establecer como un argumento JVM o vía System.setProperty ).

IBM tiene una publicación bastante detallada sobre cómo maneja WebSphere el almacenamiento here caché de DNS here . La pieza relevante para lo anterior es:

Para deshabilitar el almacenamiento en caché de direcciones para servicios web, debe establecer una propiedad personalizada JVM adicional disableWSAddressCaching en verdadero. Utilice esta propiedad para deshabilitar el almacenamiento en caché de direcciones para servicios web. Si su sistema normalmente se ejecuta con muchos subprocesos de cliente y encuentra contención de bloqueo en el caché de wsAddrCache, puede establecer esta propiedad personalizada en verdadera para evitar el almacenamiento en caché de los datos de los servicios web.


Según la respuesta de By Byron, no puede establecer networkaddress.cache.ttl o networkaddress.cache.negative.ttl como System Properties utilizando el -D o llamando a System.setProperty porque estas no son propiedades del sistema, son propiedades de seguridad .

Si desea utilizar una propiedad del sistema para desencadenar este comportamiento (para que pueda usar el distintivo -D o llamar a System.setProperty ), querrá establecer la siguiente propiedad del sistema :

-Dsun.net.inetaddr.ttl=0

Esta propiedad del sistema permitirá el efecto deseado.

Pero tenga en cuenta: si no usa el -D al iniciar el proceso de JVM y opta por llamarlo de este modo:

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

Este código debe ejecutarse antes de que cualquier otro código en la JVM intente realizar operaciones de red.

Esto es importante porque, por ejemplo, si llamaras a Security.setProperty en un archivo .war e implementaras .war en Tomcat, esto no funcionaría: Tomcat usa la pila de redes de Java para inicializarse mucho antes que tu código .war ejecutado. Debido a esta ''condición de carrera'', generalmente es más conveniente usar el indicador -D al iniciar el proceso de JVM.

Si no usa -Dsun.net.inetaddr.ttl=0 o llama a Security.setProperty , tendrá que editar $JRE_HOME/lib/security/java.security y establecer esas propiedades de seguridad en ese archivo, por ejemplo

networkaddress.cache.ttl = 0 networkaddress.cache.negative.ttl = 0

Pero preste atención a las advertencias de seguridad en los comentarios que rodean esas propiedades. Solo haga esto si tiene una confianza razonable en que no es susceptible a los ataques de falsificación de DNS .