//最新版本参见https://github.com/karlseguin/dnscache地址 或者  https://github.com/netroby/dnscache   

package dnscache
// Package dnscache caches DNS lookups

import (
  "net"
  "sync"
  "time"
)
//一个域名可能对应多个ip
type Resolver struct {
  lock sync.RWMutex   //锁--读写锁
  cache map[string][]net.IP  //map中key 为address ,value为域名对应的ip结合集合
}
//参数 refreshRate   设置刷新周期
func New(refreshRate time.Duration) *Resolver {
  resolver := &Resolver {
    cache: make(map[string][]net.IP, 64),
  }
  if refreshRate > 0 {//当刷新周期大于零  开启一个协程来自动解析域名,再次填充cache
    go resolver.autoRefresh(refreshRate)
  }
  return resolver
}
//解析域名对应的ip集合  如果在当前缓存中不存在  ,重新解析并返回
func (r *Resolver) Fetch(address string) ([]net.IP, error) {
  r.lock.RLock()
  ips, exists := r.cache[address]
  r.lock.RUnlock()
  if exists { return ips, nil }

  return r.Lookup(address)
}
//解析域名对应的ip集合中第一个ip
func (r *Resolver) FetchOne(address string) (net.IP, error) {
  ips, err := r.Fetch(address)
  if err != nil || len(ips) == 0 { return nil, err}
  return ips[0], nil
}
//解析域名对应的ip集合第一个ip的String方法
func (r *Resolver) FetchOneString(address string) (string, error) {
  ip, err := r.FetchOne(address)
  if err != nil || ip == nil { return "", err }
  return ip.String(), nil
}
//解析当前cache中所有的域名 并且处于阻塞中2秒  。每一个域名对应一个ip集合 并存储在cache中
func (r *Resolver) Refresh() {
  i := 0
  r.lock.RLock()//获取读锁
  addresses := make([]string, len(r.cache)) //创建一个slice  初始容量为 cache大小  用来存储当前的域名
  for key, _ := range r.cache {
    addresses[i] = key
    i++
  }
  r.lock.RUnlock()

  for _, address := range addresses {
    r.Lookup(address)
    time.Sleep(time.Second * 2)
  }
}
//通过net包 解析域名对应的ip集合
func (r *Resolver) Lookup(address string) ([]net.IP, error) {
  ips, err := net.LookupIP(address)
  if err != nil { return nil, err }

  r.lock.Lock()
  r.cache[address] = ips
  r.lock.Unlock()
  return ips, nil
}
//参数 rate   刷新周期
func (r *Resolver) autoRefresh(rate time.Duration) {
  for {
    time.Sleep(rate) //睡眠rate周期  并且处于阻塞中
    r.Refresh()
  }
}

dnscache --源码笔记的更多相关文章

  1. Zepto源码笔记(一)

    最近在研究Zepto的源码,这是第一篇分析,欢迎大家继续关注,第一次写源码笔记,希望大家多指点指点,第一篇文章由于首次分析原因不会有太多干货,希望后面的文章能成为各位大大心目中的干货. Zepto是一 ...

  2. redis源码笔记(一) —— 从redis的启动到command的分发

    本作品采用知识共享署名 4.0 国际许可协议进行许可.转载联系作者并保留声明头部与原文链接https://luzeshu.com/blog/redis1 本博客同步在http://www.cnblog ...

  3. AsyncTask源码笔记

    AsyncTask源码笔记 AsyncTask在注释中建议只用来做短时间的异步操作,也就是只有几秒的操作:如果是长时间的操作,建议还是使用java.util.concurrent包中的工具类,例如Ex ...

  4. Java Arrays 源码 笔记

    Arrays.java是Java中用来操作数组的类.使用这个工具类可以减少平常很多的工作量.了解其实现,可以避免一些错误的用法. 它提供的操作包括: 排序 sort 查找 binarySearch() ...

  5. Tomcat8源码笔记(八)明白Tomcat怎么部署webapps下项目

    以前没想过这么个问题:Tomcat怎么处理webapps下项目,并且我访问浏览器ip: port/项目名/请求路径,以SSM为例,Tomcat怎么就能将请求找到项目呢,项目还是个文件夹类型的? Tom ...

  6. Tomcat8源码笔记(七)组件启动Server Service Engine Host启动

    一.Tomcat启动的入口 Tomcat初始化简单流程前面博客介绍了一遍,组件除了StandardHost都有博客,欢迎大家指文中错误.Tomcat启动类是Bootstrap,而启动容器启动入口位于 ...

  7. Tomcat8源码笔记(六)连接器Connector分析

    根据 Tomcat8源码笔记(五)组件Container分析 前文分析,StandardService的初始化重心由 StandardEngine转移到了Connector的初始化,本篇记录下Conn ...

  8. Tomcat8源码笔记(五)组件Container分析

    Tomcat8源码笔记(四)Server和Service初始化 介绍过Tomcat中Service的初始化 最先初始化就是Container,而Container初始化过程是咋样的? 说到Contai ...

  9. Tomcat8源码笔记(四)Server和Service初始化

    上一章 简单说明下Tomcat各个组件: Server:服务器,Tomcat服务器,一个Tomcat只有一个Server组件; Service:业务层,是Server下最大的子容器,一个Server可 ...

随机推荐

  1. python select.select模块通信全过程详解

    要理解select.select模块其实主要就是要理解它的参数, 以及其三个返回值.select()方法接收并监控3个通信列表, 第一个是所有的输入的data,就是指外部发过来的数据,第2个是监控和接 ...

  2. 记一次线上coredump事故

    1.事故背景 上周三凌晨,我负责的某个模块在多台机器上连续发生coredump,幸好发生在业务低峰期,而且该模块提供的功能也不是核心流程功能,所以对线上业务影响比较小.发生coredump后,运维收到 ...

  3. OpenLayers3的WMS空间查询实现多个图层

    空间查询前面的帖子写过,但是在一次性查询多个图层的时候卡了一下,再次记录下. 1.WMS数据源: var wmsSource = new ol.source.TileWMS({ url:'http:/ ...

  4. spring boot + quartz 集群

    spring boot bean配置: @Configuration public class QuartzConfig { @Value("${quartz.scheduler.insta ...

  5. 《转》Xcode 6 正式版如何创建一个Empty Application

    Xcode 6 正式版里面没有Empty Application这个模板,这对于习惯了纯代码编写UI界面的程序员来说很不习惯. 有网友给出了一个解决方法是,把Xcode 6 beta版里面的模板复制过 ...

  6. Python高阶函数之 - 装饰器

    高阶函数:  1. 函数名可以作为参数传入     2. 函数名可以作为返回值. python装饰器是用于拓展原来函数功能的一种函数 , 这个函数的特殊之处在于它的返回值也是一个函数 , 使用pyth ...

  7. Eclipse下无法编译,或者WEB-INF/classes目录下没文件,编译失败的解决办法

    1. 确保 project->build automatically 已经被选上. 2. 如果选上了,也不好使, 使用这一招: project->clean..->选第2个clean ...

  8. Angularjs $http服务的两个request安全问题

    今天为了hybrid app和后端restful服务的安全认证问题,又翻了一下$http的文档,$http服务文档页面两个安全问题是json和XSRF,JSON那个比较好理解,就不补充什么了,说说XS ...

  9. SOFA 源码分析 — 预热权重

    前言 SOFA-RPC 支持根据权重对服务进行预热功能,具体地址:预热权重. 引用官方文档: 预热权重功能让客户端机器能够根据服务端的相应权重进行流量的分发.该功能也常被用于集群内少数机器的启动场景. ...

  10. ArcEngine小问题解决

    最近开始使用VS2012,在引用COM组件的时候,出现了无法嵌入互操作类型“……”,请改用适用的接口的错误提示. 找到解决方案:选中项目中引入的dll,鼠标右键,选择属性,把“嵌入互操作类型”设置为F ...