美文网首页
# Java DNS Cache

# Java DNS Cache

作者: RyanEngineer | 来源:发表于2018-07-02 21:13 被阅读0次

Cache Type

DNS的缓存类型分为两种:Positive和Negative,Positive用于缓存可以正常解析的域名,Negative用于缓存无法解析的域名。

        enum Type {Positive, Negative};

InetAddressCachePolicy

InetAddressCachePolicy(sun.net.InetAddressCachePolicy),表示缓存策略,这里特指缓存过期时间,

  private static int cachePolicy = -1;
  private static int negativeCachePolicy = 0;

  public static synchronized int get() {
    return cachePolicy;
  }

  public static synchronized int getNegative() {
    return negativeCachePolicy;
  }
  • cachePolicy,表示Positive缓存的过期时间,通过方法get()获取;
  • negativeCachePolicy,表示Negative缓存的过期时间,通过getNegative()获取;

cachePolicy和negativeCachePolicy都是静态变量,它们的数值也是通过静态代码块初始化的。

cachePolicy

    Integer var0 = (Integer)AccessController.doPrivileged(new PrivilegedAction<Integer>() {
      public Integer run() {
        String var1;
        try {
          var1 = Security.getProperty("networkaddress.cache.ttl");
          if (var1 != null) {
            return Integer.valueOf(var1);
          }
        } catch (NumberFormatException var3) {
          ;
        }

        try {
          var1 = System.getProperty("sun.net.inetaddr.ttl");
          if (var1 != null) {
            return Integer.decode(var1);
          }
        } catch (NumberFormatException var2) {
          ;
        }

        return null;
      }
    });
    if (var0 != null) {
      cachePolicy = var0;
      if (cachePolicy < 0) {
        cachePolicy = -1;
      }

      propertySet = true;
    } else if (System.getSecurityManager() == null) {
      cachePolicy = 30;
    }

cachePolicy取值来源于两个配置属性:

  • networkaddress.cache.ttl(优先级高)
  • sun.net.inetaddr.ttl(优先级低)

如果配置属性的值小于0,则cachePolicy为-1;如果配置属性没有被设置,则cachePolicy为30。也就是说,对于正常解析的域名,默认的缓存时间为30s。

:-1为永久缓存。

negativeCachePolicy

    var0 = (Integer)AccessController.doPrivileged(new PrivilegedAction<Integer>() {
      public Integer run() {
        String var1;
        try {
          var1 = Security.getProperty("networkaddress.cache.negative.ttl");
          if (var1 != null) {
            return Integer.valueOf(var1);
          }
        } catch (NumberFormatException var3) {
          ;
        }

        try {
          var1 = System.getProperty("sun.net.inetaddr.negative.ttl");
          if (var1 != null) {
            return Integer.decode(var1);
          }
        } catch (NumberFormatException var2) {
          ;
        }

        return null;
      }
    });
    if (var0 != null) {
      negativeCachePolicy = var0;
      if (negativeCachePolicy < 0) {
        negativeCachePolicy = -1;
      }

      propertyNegativeSet = true;
    }

negativeCachePolicy取值来源于两个配置属性:

  • networkaddress.cache.negative.ttl(优先级高)
  • sun.net.inetaddr.negative.ttl(优先级低)

如果配置属性的值小于0,则negativeCachePolicy为-1;如果配置属性的值没有被设置,则negativeCachePolicy为0。也就是说,对于无法解析的域名,默认的缓存时间为0s,即不缓存。

CacheEntry

CacheEntry(java.net.InetAddress.CacheEntry),表示一个缓存对象,包含两个实例属性:

  • addresses ,IP地址,一个域名可以对应着多个IP地址)
  • expiration,过期时间;
    /**
     * Represents a cache entry
     */
    static final class CacheEntry {

        CacheEntry(InetAddress[] addresses, long expiration) {
            this.addresses = addresses;
            this.expiration = expiration;
        }

        InetAddress[] addresses;
        long expiration;
    }

Cache

Cache(java.net.InetAddress.Cache),表示一个缓存实例,包含两个实例属性:

  • cache,缓存的具体实现,实际就是一个HashMap(LinkedHashMap);
  • type,缓存类型,Positive或Negative;
        private LinkedHashMap<String, CacheEntry> cache;
        private Type type;

put

  1. 根据缓存类型,获取相应的缓存时间;如果缓存时间为0s,则put直接退出即可;
            int policy = getPolicy();
            if (policy == InetAddressCachePolicy.NEVER) {
                return this;
            }
  1. 如果不是永久缓存,则清理缓存中的过期对象;
            // 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<String> expired = new LinkedList<>();
                long now = System.currentTimeMillis();
                for (String key : cache.keySet()) {
                    CacheEntry entry = cache.get(key);

                    if (entry.expiration >= 0 && entry.expiration < now) {
                        expired.add(key);
                    } else {
                        break;
                    }
                }

                for (String key : expired) {
                    cache.remove(key);
                }

逐个遍历缓存中的对象(entry),判断是否过期;如果已过期(entry.expiration < now),则将域名加入到过期列表(expired);遍历完成之后,将过期列表中的域名统一从缓存中清除。

  1. 计算对象对象过期时间(expiration),将对象存入缓存;
            long expiration;
            if (policy == InetAddressCachePolicy.FOREVER) {
                expiration = -1;
            } else {
                expiration = System.currentTimeMillis() + (policy * 1000);
            }
            CacheEntry entry = new CacheEntry(addresses, expiration);
            cache.put(host, entry);

get

  1. 根据缓存类型,获取相应的缓存时间;如果缓存时间为0s,则get直接返回null即可;
            int policy = getPolicy();
            if (policy == InetAddressCachePolicy.NEVER) {
                return null;
            }

  1. 通过域名(host)获取相应的缓存对象(IP地址);
            CacheEntry entry = cache.get(host);
  1. 判断缓存对象是否过期;如果已过期,需要从缓存中移出(域名指向可能已发生变化),并返回null;
            // check if entry has expired
            if (entry != null && policy != InetAddressCachePolicy.FOREVER) {
                if (entry.expiration >= 0 &&
                    entry.expiration < System.currentTimeMillis()) {
                    cache.remove(host);
                    entry = null;
                }
            }

InetAddress getByName

InetAddress.getByName底层域名解析实际调用的方法为InetAddress.getAllByName0,主要包括两个核心逻辑:

  • getCachedAddresses,从缓存中获取指定域名的IP地址;
  • getAddressesFromNameService,如果缓存中没有获取到指定域名的IP地址,则通过DNS服务来解析;

通过DNS服务解析域名之后,无论是否能够正常解析,均需要更新缓存:

    // Cache the address.
    cacheAddresses(host, addresses, success);

    /*
     * Cache the given hostname and addresses.
     */
    private static void cacheAddresses(String hostname,
                                       InetAddress[] addresses,
                                       boolean success) {
        hostname = hostname.toLowerCase();
        synchronized (addressCache) {
            cacheInitIfNeeded();
            if (success) {
                addressCache.put(hostname, addresses);
            } else {
                negativeCache.put(hostname, addresses);
            }
        }
    }

:无法正常解析的域名,IP地址被缓存为unknown_array。

相关文章

  • # Java DNS Cache

    Cache Type DNS的缓存类型分为两种:Positive和Negative,Positive用于缓存可以正...

  • DNS解析步骤

    1.应用发起基于域名的请求后,linux先查询本地dns cache。 2.本地dns cache命中(cache...

  • 【jvm&DNS】关于java dns cache

    我们上网的原点就是打开浏览器,在上方地址栏输入网址的那一刻,这个回车按了之后,发生了很多事情。 首先,计算机只懂0...

  • Mac 刷新DNS

    Reset the DNS cache in OS X 关于DNS缓存 OS X在DNS服务器定义的时间内保留已解...

  • DNS缓存服务 — NSCD

    原文:https://www.fanhaobai.com/2017/06/nscd-dns-cache.html ...

  • 浏览器输入 URL 请求的全过程

    浏览器输入 URL 请求的全过程 1. DNS 解析 按照一下顺序进行 DNS 解析: Browser cache...

  • Android-UIL-cache

    Cache pkg cache包目录 disk cache 1.DiskCache.java 该接口是本地内存操作...

  • 题目

    1.dns(解析域名)--tcp3次握手--request-cache-response--构建:DOM 树(节点...

  • Reset the DNS cache in OS X

    https://support.apple.com/en-us/HT202516 Use the followin...

  • Springboot Redis @Cacheable

    java.lang.IllegalStateException: No cache could be resolv...

网友评论

      本文标题:# Java DNS Cache

      本文链接:https://www.haomeiwen.com/subject/kdkruftx.html