Pertanyaan Ada cara untuk membuat Java menghormati DNS Caching Timeout (TTL)?


Kami menggunakan GSLB untuk geo-distribusi dan load-balancing. Setiap layanan diberi nama domain tetap. Melalui beberapa keajaiban DNS, nama domain diselesaikan menjadi IP yang paling dekat dengan server dengan beban paling sedikit. Agar load-balancing berfungsi, server aplikasi harus menghormati TTL dari respons DNS dan untuk menyelesaikan kembali nama domain saat cache habis. Namun, saya tidak dapat menemukan cara untuk melakukan ini di Jawa.

Aplikasi ini di Java 5, berjalan di Linux (Centos 5).


75
2017-08-10 18:49


asal


Jawaban:


Java memiliki beberapa perilaku caching dns yang sangat aneh. Taruhan terbaik Anda adalah untuk mematikan cache dns atau mengaturnya ke beberapa angka rendah seperti 5 detik.

networkaddress.cache.ttl (default: -1)
    Menunjukkan kebijakan caching untuk pencarian nama yang sukses dari layanan nama. Nilai ditetapkan sebagai bilangan bulat untuk menunjukkan jumlah detik untuk meng-cache pencarian yang berhasil. Nilai -1 menunjukkan "cache selamanya".

networkaddress.cache.negative.ttl (default: 10)
    Menunjukkan kebijakan caching untuk pencarian nama yang tidak berhasil dari layanan nama. Nilai ditetapkan sebagai bilangan bulat untuk menunjukkan jumlah detik untuk menyimpan kegagalan untuk pencarian yang tidak berhasil. Nilai 0 menunjukkan "tidak pernah tembolok". Nilai -1 menunjukkan "cache selamanya".


55
2017-08-10 19:00



Jawaban Per Byron, Anda tidak bisa mengatur networkaddress.cache.ttl atau networkaddress.cache.negative.ttl sebagai System Properties dengan menggunakan -D bendera atau panggilan System.setProperty karena ini bukan properti Sistem - mereka Keamanan properti.

Jika Anda ingin menggunakan properti Sistem untuk memicu perilaku ini (sehingga Anda dapat menggunakan -D bendera atau panggilan System.setProperty), Anda akan ingin mengatur yang berikut ini Sistem milik:

-Dsun.net.inetaddr.ttl=0

Properti sistem ini akan mengaktifkan efek yang diinginkan.

Namun perlu diperhatikan: jika Anda tidak menggunakan -D Tandai ketika memulai proses JVM dan pilih untuk memanggil ini dari kode sebagai gantinya:

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

Kode ini harus jalankan sebelum kode lain di JVM mencoba untuk melakukan operasi jaringan.

Ini penting karena, misalnya, jika Anda menelepon Security.setProperty dalam file .war dan menyebarkannya .war ke Tomcat, ini tidak akan berfungsi: Tomcat menggunakan jaringan Java stack untuk menginisialisasi sendiri jauh lebih awal daripada kode .war Anda dijalankan. Karena ini 'kondisi lomba', biasanya lebih nyaman untuk menggunakan -D saat memulai proses JVM.

Jika Anda tidak menggunakannya -Dsun.net.inetaddr.ttl=0 atau telepon Security.setProperty, Anda perlu mengedit $JRE_HOME/lib/security/java.security dan mengatur properti keamanan tersebut di file itu, mis.

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

Namun perhatikan peringatan keamanan di komentar seputar properti tersebut. Lakukan ini hanya jika Anda cukup yakin bahwa Anda tidak rentan Serangan spoofing DNS.


44
2018-06-20 16:50



Ini jelas telah diperbaiki dalam rilis baru (SE 6 dan 7). Saya mengalami maximal waktu caching 30 detik ketika menjalankan potongan kode berikut saat menonton aktivitas port 53 menggunakan tcpdump.

/**
 * http://stackoverflow.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();
        }
    }
}

19
2017-08-10 19:33



Untuk memperluas jawaban Byron, saya yakin Anda perlu mengedit file java.security dalam %JRE_HOME%\lib\security direktori untuk mempengaruhi perubahan ini.

Inilah bagian yang relevan:

#
# 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 

Dokumentasi pada java.security mengajukan sini.


17
2018-06-03 21:12



Untuk meringkas jawaban yang lain, di <jre-path>/lib/security/java.security Anda dapat mengatur nilai properti networkaddress.cache.ttl untuk menyesuaikan cara pencarian DNS di-cache. Perhatikan bahwa ini tidak sebuah properti sistem tetapi properti keamanan. Saya dapat mengatur ini menggunakan:

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

Ini juga dapat diatur oleh properti sistem -Dsun.net.inetaddr.ttl meskipun ini tidak akan mengesampingkan properti keamanan jika diatur di tempat lain.

Saya juga ingin menambahkan bahwa jika Anda melihat masalah ini dengan layanan web di WebSphere, seperti saya, pengaturan networkaddress.cache.ttl tidak akan cukup. Anda perlu mengatur properti sistem disableWSAddressCaching untuk true. Tidak seperti properti time-to-live, ini dapat ditetapkan sebagai argumen JVM atau melalui System.setProperty).

IBM memiliki posting yang cukup rinci tentang bagaimana WebSphere menangani caching DNS sini. Bagian yang relevan di atas adalah:

Untuk menonaktifkan cache alamat untuk layanan Web, Anda perlu mengatur properti kustom JVM tambahan disableWSAddressCaching menjadi true. Gunakan properti ini untuk menonaktifkan cache alamat untuk layanan Web. Jika sistem Anda biasanya berjalan dengan banyak utas klien, dan Anda menghadapi pertentangan kunci di cache wsAddrCache, Anda bisa menyetel properti kustom ini menjadi true, untuk mencegah caching dari data layanan Web.


4
2017-10-07 23:44



Menurut properti java oracle resmi, sun.net.inetaddr.ttl adalah properti implementasi khusus Sun, yang "mungkin tidak didukung dalam rilis mendatang". "Cara yang disukai adalah menggunakan properti keamanan" networkaddress.cache.ttl.


1