zoukankan      html  css  js  c++  java
  • JDK中DNS缓存的分析

    在JAVA中使用InetAddress.getByName(String host) 方法来获取给定hostname的IP地址。为了减少DNS解析的请求次数,提高解析效率,InetAddress中提供cache来缓存解析结果。

    下面就此cache进行简单的分析:

    该缓存实现比较简单,巧妙的利用LinkedHashMap的特性来进行过期条目的检测和移除。

        /**
         * Represents a cache entry
         */
        static final class CacheEntry {
    
            CacheEntry(Object address, long expiration) {
                this.address = address;
                this.expiration = expiration;
            }
    
            Object address;
            long expiration;
        }
    
    
    //CacheEntry实例代表一个缓存记录,一个记录中包括address(IP 地址) 和 expiration
    
        /**
         * A cache that manages entries based on a policy specified
         * at creation time.
         */
        static final class Cache {
        private LinkedHashMap cache;
        private Type type;
    
        enum Type {Positive, Negative};//此缓存只提供两种缓存类型 Positive: DNS解析成功    Negative:DNS解析失败
    
        /**
         * Create cache
         */
        public Cache(Type type) {
            this.type = type;
            cache = new LinkedHashMap();//LinkedHashMap 保存了记录的插入顺序,当遍历LindedHashMap时得到的数据是最先插入的数据,此特性很重要在put方法中有所体现
        }
    
        private int getPolicy() {//获取配置的缓存策略   0: 不缓存  -1: 代表永久缓存  >=1:代表缓存的时间(unit: second)
            if (type == Type.Positive) {
            return InetAddressCachePolicy.get();
            } else {
            return InetAddressCachePolicy.getNegative();
            }
        }
    
        /**
         * Add an entry to the cache. If there's already an
         * entry then for this host then the entry will be
         * replaced.
         */
        public Cache put(String host, Object address) {
            int policy = getPolicy();
            if (policy == InetAddressCachePolicy.NEVER) {
                    return this;
            }
    
            // purge any expired entries
    
            if (policy != InetAddressCachePolicy.FOREVER) {
    
            // As we iterate in insertion order we can
            // terminate when a non-expired entry is found.
                    LinkedList expired = new LinkedList();
                    Iterator i = cache.keySet().iterator();//每次put的时候都对缓存记录做一个清理,由于每个条目的过期时间是一样的,所以先插入的记录就先到期
            long now = System.currentTimeMillis();
                    while (i.hasNext()) {
                        String key = (String)i.next();
                        CacheEntry entry = (CacheEntry)cache.get(key);
    
                        if (entry.expiration >= 0 && entry.expiration < now) {
                            expired.add(key);
                        } else {
                            break;
                        }
                    }
    
                    i = expired.iterator();
                    while (i.hasNext()) {
                        cache.remove(i.next());
            }
                }
    
            // create new entry and add it to the cache
            // -- as a HashMap replaces existing entries we
            //    don't need to explicitly check if there is
            //    already an entry for this host.
            long expiration;
            if (policy == InetAddressCachePolicy.FOREVER) {
            expiration = -1;
            } else {
            expiration = System.currentTimeMillis() + (policy * 1000);
            }
            CacheEntry entry = new CacheEntry(address, expiration);
            cache.put(host, entry);
            return this;
        }
    
        /**
         * Query the cache for the specific host. If found then
         * return its CacheEntry, or null if not found.
         */
        public CacheEntry get(String host) {
            int policy = getPolicy();
            if (policy == InetAddressCachePolicy.NEVER) {
            return null;
            }
            CacheEntry entry = (CacheEntry)cache.get(host);
    
            // check if entry has expired
            if (entry != null && policy != InetAddressCachePolicy.FOREVER) {//命中缓存条目后先判断是否过期
            if (entry.expiration >= 0 &&
                entry.expiration < System.currentTimeMillis()) {
                cache.remove(host);
                entry = null;
            }
            }
    
            return entry;
        }
        }
  • 相关阅读:
    LeetCode题解——冗余连接(并查集)——java实现
    两数之和的问题
    强引用、软引用、弱引用、虚引用——4中引用的理解
    手写死锁程序实例
    使用阻塞队列实现生产者消费者问题
    ABC三个线程交替打印10遍,要求A打印5次,B打印10次,C打印15次
    使用jstack查看线程情况解决cpu飙高问题
    ES 【elasticsearch】
    C# 正则
    领域驱动设计 浅析VO、DTO、DO、PO的概念、区别和用处等资料链接(草稿)
  • 原文地址:https://www.cnblogs.com/cruze/p/3707011.html
Copyright © 2011-2022 走看看