जावा कैशिंग टाइमआउट को जावा सम्मान कैसे दें?


101

हम भू-वितरण और लोड-संतुलन के लिए जीएसएलबी का उपयोग करते हैं। प्रत्येक सेवा को एक निश्चित डोमेन नाम सौंपा गया है। कुछ DNS जादू के माध्यम से, डोमेन नाम को एक आईपी में हल किया जाता है जो सर्वर पर कम से कम लोड के साथ निकटतम होता है। काम के लिए लोड-बैलेंसिंग के लिए, एप्लिकेशन सर्वर को DNS प्रतिक्रिया से TTL का सम्मान करने और कैश समय समाप्त होने पर डोमेन नाम को फिर से हल करने की आवश्यकता होती है। हालाँकि, मैं जावा में ऐसा करने का कोई तरीका नहीं निकाल सका।

एप्लिकेशन जावा 5 में है, लिनक्स (सेंटोस 5) पर चल रहा है।

जवाबों:


76

बायरन के उत्तर के अनुसार, आप ध्वज का उपयोग करके networkaddress.cache.ttlया networkaddress.cache.negative.ttlसिस्टम गुण के रूप में सेट -Dया कॉल System.setPropertyनहीं कर सकते क्योंकि ये सिस्टम गुण नहीं हैं - वे सुरक्षा गुण हैं।

यदि आप इस व्यवहार को ट्रिगर करने के लिए सिस्टम गुण का उपयोग करना चाहते हैं (ताकि आप -Dध्वज या कॉल का उपयोग कर सकें System.setProperty), तो आप निम्न सिस्टम सिस्टम सेट करना चाहेंगे :

-Dsun.net.inetaddr.ttl=0

यह सिस्टम गुण वांछित प्रभाव को सक्षम करेगा।

लेकिन ध्यान रखें: यदि आप -DJVM प्रक्रिया को शुरू करते समय ध्वज का उपयोग नहीं करते हैं और इसके बजाय कोड से कॉल करने का चुनाव करते हैं:

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

यह कोड नेटवर्किंग संचालन करने के लिए JVM के किसी अन्य कोड से पहले निष्पादित होना चाहिए

यह महत्वपूर्ण है क्योंकि, उदाहरण के लिए, यदि आप Security.setPropertyएक .war फ़ाइल में कॉल करते हैं और उस .war को Tomcat पर तैनात करते हैं, तो यह काम नहीं करेगा: Tomcat जावा नेटवर्किंग स्टैक का उपयोग खुद को आपके .war के कोड को निष्पादित करने से पहले शुरू करने के लिए करता है। इस 'रेस कंडीशन' की वजह से, -Dजेवीएम प्रक्रिया शुरू करते समय आमतौर पर ध्वज का उपयोग करना अधिक सुविधाजनक होता है।

यदि आप उपयोग -Dsun.net.inetaddr.ttl=0या कॉल नहीं करते हैं Security.setProperty, तो आपको $JRE_HOME/lib/security/java.securityउस फ़ाइल में उन सुरक्षा गुणों को संपादित और सेट करना होगा, जैसे

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

लेकिन उन संपत्तियों के बारे में टिप्पणियों में सुरक्षा चेतावनी पर ध्यान दें। ऐसा केवल तभी करें जब आप उचित रूप से आश्वस्त हों कि आप डीएनएस स्पूफिंग हमलों के लिए अतिसंवेदनशील नहीं हैं ।


2
FQN है java.security.Security(कम से कम jdk7 में)
पाब्लो फर्नांडीज

1
बस एक टिप्पणी, उन सुरक्षा चेतावनियाँ ज्यादातर सुरक्षा प्रबंधकों और रिमोट लोडिंग के संबंध में हैं। किसी भी सामान्य सर्वर एप्लिकेशन के लिए जो डीएसएल पर भरोसा करता है, टीटीएल को कम करने के लिए कुछ को ठीक करता है। (हालांकि मुझे नहीं लगता कि 0 एक अच्छा न्यूनतम है और गैर-सुरक्षा प्रबंधकों के लिए 30 का डिफ़ॉल्ट अधिकांश मामलों में ठीक है)।
Eckes

3
क्या सिस्टम प्रॉपर्टी OpenJDK के साथ भी काम करती है या यह Oracle विशिष्ट है?
mhlz

67

जावा में कुछ गंभीर रूप से अजीब डीएनएस कैशिंग व्यवहार है। आपका सबसे अच्छा शर्त यह है कि dns कैशिंग बंद करें या इसे 5 सेकंड की तरह कुछ कम संख्या में सेट करें।

networkaddress.cache.ttl (डिफ़ॉल्ट: -1)
नाम सेवा से सफल नाम लुकअप के लिए कैशिंग नीति को इंगित करता है। सफल लुकअप को कैश करने के लिए सेकंड की संख्या को इंगित करने के लिए मान को पूर्णांक के रूप में निर्दिष्ट किया गया है। -1 का मान "कैश को हमेशा के लिए" इंगित करता है।

networkaddress.cache.negative.ttl (डिफ़ॉल्ट: 10)
नाम सेवा से अन-सफल नाम लुकअप के लिए कैशिंग नीति को इंगित करता है। मान को पूर्ण-सफल लुकअप के लिए विफलता को कैश करने के लिए सेकंड की संख्या को इंगित करने के लिए पूर्णांक के रूप में निर्दिष्ट किया गया है। 0 का मान "कभी कैश नहीं" इंगित करता है। -1 का मान "कैश को हमेशा के लिए" इंगित करता है।


7
नोट: यह आपके OS में सभी DNS कैशिंग को अक्षम नहीं करता है। बस लाइब्रेरी में जावा की अपनी टूटी-फूटी मेमोरी कैशिंग को निष्क्रिय कर देता है। जब आप JVM आह्वान करते हैं, तो आप बस इन गुणों को कमांड लाइन पर सेट कर सकते हैं।
नेल्सन 19

2
मुझे नहीं पता कि "टूटी" वैध है। जावा (सुरक्षा कारणों से) DNS प्रविष्टियों को हमेशा के लिए कैश करता है, या जब तक कि जेवीएम को फिर से शुरू नहीं किया जाता है, जो भी पहले आता है। यह (जो मैं बता सकता हूं) डिजाइन द्वारा था। सेटिंग java.security पॉलिसी फ़ाइल में या कमांड लाइन पर की जा सकती है। सेटिंग्स प्रत्येक के लिए अलग हैं। संदर्भ: rgagnon.com/javadetails/java-0445.html
मिलनर

4
ध्यान दें कि आप इन्हें सिस्टम गुण (यानी -D झंडे या System.setProperty का उपयोग करके) सेट नहीं कर सकते क्योंकि वे सिस्टम गुण नहीं हैं - सुरक्षा गुण।
लेस हेज़लवुड

6
यह प्रलेखन 1.7 में थोड़ा अलग है। विशेष रूप से, कैश हमेशा अब केवल तभी होता है जब एक सुरक्षा प्रबंधक मौजूद होता है: "सुरक्षा प्रबंधक स्थापित होने पर, और एक सुरक्षा प्रबंधक स्थापित नहीं होने पर कार्यान्वयन की विशिष्ट अवधि के लिए कैश करने के लिए डिफ़ॉल्ट व्यवहार हमेशा के लिए कैश होता है।" docs.oracle.com/javase/7/docs/technotes/guides/net/…
ब्रेट ओकेन

1
देख @Michael System.getSecurityManager()। Java 8 के लिए डॉक्स: docs.oracle.com/javase/8/docs/api/java/lang/…
gesellix

22

यह स्पष्ट रूप से नए रिलीज (एसई 6 और 7) में तय किया गया है। जब मैं tcpdump का उपयोग करके पोर्ट 53 गतिविधि देख रहा हूं, तो निम्नलिखित कोड स्निपेट को चलाते समय 30 सेकंड के कैशिंग समय का अधिकतम अनुभव करता हूं।

/**
 * 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();
        }
    }
}

16
हां, जावा 1.5 में अनंत कैशिंग का एक डिफ़ॉल्ट मूल्य था। जावा 1.6 और 1.7 में 30 सेकंड का डिफ़ॉल्ट है।
माइकल

7
1.7 के लिए प्रलेखन यह इंगित करता है कि यह केवल उस मामले में सच हो सकता है जहां एक सुरक्षा प्रबंधक मौजूद नहीं है: "सुरक्षा प्रबंधक को स्थापित करने के लिए डिफ़ॉल्ट व्यवहार को हमेशा के लिए कैश करना है, और कार्यान्वयन की विशिष्ट अवधि के लिए कैश करना है, जब एक सुरक्षा प्रबंधक स्थापित नहीं है। " docs.oracle.com/javase/7/docs/technotes/guides/net/…
ब्रेट ओकेन

1
@ मिचेल केयर उस जानकारी के लिए स्रोत साझा करने के लिए?
rustyx

4
@rustyx Oracle के 1.6 और 1.7 JDK के पास jre / lib / Security / java.security के लिए networkaddress.cache.ttl है: "# डिफ़ॉल्ट मान हमेशा के लिए है (FOREVER)। सुरक्षा कारणों से, यह कैशिंग सुरक्षा प्रबंधक के हमेशा के लिए बना दिया जाता है। जब कोई सुरक्षा # प्रबंधक सेट नहीं होता है, तो डिफ़ॉल्ट व्यवहार 30 सेकंड के लिए कैश करना होता है। " तो जावा वेब स्टार्ट के माध्यम से तैनात एप्लेट्स और एप्स अभी भी हमेशा के लिए कैश हो जाते हैं अन्यथा यह 30 सेकंड है।
माइकल

1
यहाँ OpenJDK 8 के java.security का एक कोड पॉइंटर है, जो कहता है कि बिना सुरक्षा प्रबंधक के TTL 30s: hg.openjdk.java.net/jdk8u/jdk8u/jdk/file/f940e7a48b72/src/share/… है । मैंने मैक ओएस एक्स और उबंटू 14.04 पर इसका परीक्षण किया।
सैन्य

18

बायरन के उत्तर पर विस्तार करने के लिए, मेरा मानना ​​है कि आपको इस परिवर्तन को प्रभावित करने के java.securityलिए %JRE_HOME%\lib\securityनिर्देशिका में फ़ाइल को संपादित करने की आवश्यकता है ।

यहाँ प्रासंगिक अनुभाग है:

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

यहाँjava.security फ़ाइल पर प्रलेखन ।


5
इसे जोड़ने के लिए, tomcat6 का उपयोग करते समय मुझे अपनी lib / सुरक्षा फ़ाइल को संशोधित करना था, जैसा कि networkaddress.cache.ttl या sun.net.inetaddr.ttl को प्रोग्रामेटिक रूप से सेट करना या JAVA_OPER वेरिएबल के माध्यम से काम नहीं करना है।
बजे

1
@bramp धन्यवाद भाई, मैं भी आपकी समस्या का सामना कर रहा हूं और आपकी टिप्पणी और उत्तर का उपयोग करके टिप्पणी और उत्तर के लिए +1 का समाधान कर रहा हूं।
भाविक अंबानी

7

अन्य उत्तरों को सारांशित करने के लिए, <jre-path>/lib/security/java.securityआप networkaddress.cache.ttlDNS लुकअप को कैश करने के लिए समायोजित करने के लिए गुण का मान सेट कर सकते हैं। ध्यान दें कि यह है नहीं एक प्रणाली संपत्ति लेकिन एक सुरक्षा संपत्ति। मैं इसका उपयोग करने में सक्षम था:

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

यह सिस्टम प्रॉपर्टी द्वारा भी सेट किया जा सकता है -Dsun.net.inetaddr.ttl हालांकि यह एक सुरक्षा प्रॉपर्टी को ओवरराइड नहीं करेगा यदि इसे कहीं और सेट किया गया है।

मैं यह भी जोड़ना चाहूंगा कि यदि आप इस मुद्दे को वेबसेफ़र में वेब सेवाओं के साथ देख रहे हैं, जैसा कि मैं था, तो सेटिंग networkaddress.cache.ttlपर्याप्त नहीं होगी। आपको सिस्टम प्रॉपर्टी disableWSAddressCachingको सेट करना होगा true। समय-लाइव संपत्ति के विपरीत, यह एक जेवीएम तर्क या के माध्यम से सेट किया जा सकता है System.setProperty)।

आईबीएम के पास एक विस्तृत विस्तृत पोस्ट है कि कैसे WebSphere यहाँ DNS कैशिंग को संभालता है । उपरोक्त टुकड़ा संबंधित है:

वेब सेवाओं के लिए एड्रेस कैशिंग को अक्षम करने के लिए, आपको एक अतिरिक्त JVM कस्टम प्रॉपर्टी को अक्षम करने की आवश्यकता है। वेब सेवाओं के लिए पता कैशिंग अक्षम करने के लिए इस गुण का उपयोग करें। यदि आपका सिस्टम आमतौर पर बहुत सारे क्लाइंट थ्रेड्स के साथ चलता है, और आप wsAddrCache कैश पर लॉक कॉन्टेंट का सामना करते हैं, तो आप वेब सेवाओं के डेटा की कैशिंग को रोकने के लिए, इस कस्टम प्रॉपर्टी को सही पर सेट कर सकते हैं।


2

आधिकारिक ऑर्कल जावा गुणों के अनुसार , sun.net.inetaddr.ttlसूर्य कार्यान्वयन-विशिष्ट संपत्ति है, जो "भविष्य के रिलीज में समर्थित नहीं हो सकती है"। "सुरक्षा संपत्ति का उपयोग करने का पसंदीदा तरीका है" networkaddress.cache.ttl

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.