域名解析和缓存

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 ResolutionThe 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 resolverThe 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 exampleimport ( "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 exampleimport ( "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

    推荐阅读