美文网首页
域名解析和缓存

域名解析和缓存

作者: 7亮 | 来源:发表于2019-06-27 01:14 被阅读0次

    name resolve

    当浏览器访问某个网站域名或者应用服务通过域名方式访问API接口的时候,需要用IP和port建立TCP连接或者复用底层连接,IP地址的获取依赖对域名的解析,完成解析的角色称为域名解析器(dns resolver)。解析的大致过程就是检查cache是否有该记录,本地hosts文件是否有,都没有命中就查询dns server进行CNAME和A记录的查询。在linux系统下,dns server的IP一般在/etc/resolv.conf文件中。
    域名解析常用dig命令,以及在https://www.whatsmydns.net/进行域名解析测试。

    dns resolver cache(dns cache)

    考虑到域名IP地址不是经常变动,减少查询dns的冗余,并显著降低高QPS应用服务查询dns的压力(最后一节有benchmark对比),需要对dns信息进行缓存。因为软件应用不同、开发语言不同、操作系统不同,dns resolver的实现和封装也不同,会遇到不同的层面的cache。比如windows的dns resolver会有cache,linux默认不缓存;go语言可以选择cgo或者自己实现的dns resolver;chrome浏览器也会有自己的cache。
    dns cache除了好处以外,也带来了其他问题。比如dns cache可能被恶意病毒修改,将真实IP改成钓鱼网站的IP,对用户进行诱导和钓鱼。还有在服务发现的这种特定场景下,dns cache是不被允许的,会出现IP更新不及时导致API流量的损失和错误,例如部署上线或者宕机,相比之下,运维响应的时长会造成更大的损失。但为了解决这个问题,在client和server端中间增加一层代理,dns记录指向这个代理。如图:


    image.png

    代理职责一般有:

    • 服务发现,帮助客户端发现有多少服务实例。
    • 健康检查,对服务实例进行健康检查,及时剔除不健康实例,避免流量的损失。并通过此机制完成服务的无损上线。
    • 流量负载均衡。

    代理一般分为:

    类别 名称
    四层负载均衡 LVS F5
    七层负载均衡 nginx openresty

    四层代理对外暴露的IP一般称为虚IP(VIP)

    go name resolve

    • net/net.go package comment:
    Name Resolution
    
    The method for resolving domain names, whether indirectly with functions like Dial
    or directly with functions like LookupHost and LookupAddr, varies by operating system.
    
    On Unix systems, the resolver has two options for resolving names.
    It can use a pure Go resolver that sends DNS requests directly to the servers
    listed in /etc/resolv.conf, or it can use a cgo-based resolver that calls C
    library routines such as getaddrinfo and getnameinfo.
    
    By default the pure Go resolver is used, because a blocked DNS request consumes
    only a goroutine, while a blocked C call consumes an operating system thread.
    When cgo is available, the cgo-based resolver is used instead under a variety of
    conditions: on systems that do not let programs make direct DNS requests (OS X),
    when the LOCALDOMAIN environment variable is present (even if empty),
    when the RES_OPTIONS or HOSTALIASES environment variable is non-empty,
    when the ASR_CONFIG environment variable is non-empty (OpenBSD only),
    when /etc/resolv.conf or /etc/nsswitch.conf specify the use of features that the
    Go resolver does not implement, and when the name being looked up ends in .local
    or is an mDNS name.
    
    The resolver decision can be overridden by setting the netdns value of the
    GODEBUG environment variable (see package runtime) to go or cgo, as in:
    
        export GODEBUG=netdns=go    # force pure Go resolver
        export GODEBUG=netdns=cgo   # force cgo resolver
    
    The decision can also be forced while building the Go source tree
    by setting the netgo or netcgo build tag.
    
    A numeric netdns setting, as in GODEBUG=netdns=1, causes the resolver
    to print debugging information about its decisions.
    To force a particular resolver while also printing debugging information,
    join the two settings by a plus sign, as in GODEBUG=netdns=go+1.
    
    On Plan 9, the resolver always accesses /net/cs and /net/dns.
    
    On Windows, the resolver always uses C library functions, such as GetAddrInfo and DnsQuery.
    
    • go sdk做域名解析有两种策略:
    export GODEBUG=netdns=go    # force pure Go resolver
    export GODEBUG=netdns=cgo   # force cgo resolver
    
    • 写个demo测试一下有无cache的性能区别:
      example.go
    package example
    
    import (
        "net"
    )
    
    func queryDNS(name string) []net.IP {
        ips, err := net.LookupIP(name)
        if err != nil {
            panic(err)
        }
        return ips
    }
    
    func QueryDNSNoCache() []net.IP {
        return queryDNS("music.163.com")
    }
    
    func QueryDNSWithCache() []net.IP {
        return queryDNS("music.163.com")
    }
    
    

    example_test.go

    package example
    
    import (
        "os"
        "testing"
    )
    
    func BenchmarkQueryDNSNoCache(b *testing.B) {
        _ = os.Setenv("GODEBUG", "netdns=go+1")
        for i := 0; i < b.N; i++ {
            QueryDNSNoCache()
        }
    }
    
    func BenchmarkQueryDNSWithCache(b *testing.B) {
        _ = os.Setenv("GODEBUG", "netdns=cgo+1")
        for i := 0; i < b.N; i++ {
            QueryDNSWithCache()
        }
    }
    

    性能对比:


    image.png

    从对比中可看出:go的pure resolver因没有cache和网络不稳定的因素,总耗时较多。而cgo的resolver比较稳定且耗时较低。

    dns cache查看和清除

    darwin

    sudo killall -HUP mDNSResponder
    

    linux(unix)

    linux或类unix系统是没有操作系统级别的dns cache。除非安装了dnsmasq或者
    nscd(Name Service Caching Daemon),并开启。

    sudo strings /var/cache/nscd/hosts
    /etc/init.d/nscd stop
    /etc/init.d/nscd start
    sudo nscd -g
    

    windows

    ipconfig /displaydns
    ipconfig /flushdns
    

    chrome

    chrome://net-internals/#dns
    

    相关文章

      网友评论

          本文标题:域名解析和缓存

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