name resolve
當(dāng)瀏覽器訪(fǎng)問(wèn)某個(gè)網(wǎng)站域名或者應(yīng)用服務(wù)通過(guò)域名方式訪(fǎng)問(wèn)API接口的時(shí)候灵莲,需要用IP和port建立TCP連接或者復(fù)用底層連接鸟整,IP地址的獲取依賴(lài)對(duì)域名的解析,完成解析的角色稱(chēng)為域名解析器(dns resolver)毯侦。解析的大致過(guò)程就是檢查cache是否有該記錄,本地hosts文件是否有,都沒(méi)有命中就查詢(xún)dns server進(jìn)行CNAME和A記錄的查詢(xún)倦蚪。在linux系統(tǒng)下,dns server的IP一般在/etc/resolv.conf文件中边苹。
域名解析常用dig命令陵且,以及在https://www.whatsmydns.net/進(jìn)行域名解析測(cè)試。
dns resolver cache(dns cache)
考慮到域名IP地址不是經(jīng)常變動(dòng)个束,減少查詢(xún)dns的冗余慕购,并顯著降低高QPS應(yīng)用服務(wù)查詢(xún)dns的壓力(最后一節(jié)有benchmark對(duì)比),需要對(duì)dns信息進(jìn)行緩存茬底。因?yàn)檐浖?yīng)用不同沪悲、開(kāi)發(fā)語(yǔ)言不同、操作系統(tǒng)不同阱表,dns resolver的實(shí)現(xiàn)和封裝也不同殿如,會(huì)遇到不同的層面的cache。比如windows的dns resolver會(huì)有cache最爬,linux默認(rèn)不緩存涉馁;go語(yǔ)言可以選擇cgo或者自己實(shí)現(xiàn)的dns resolver;chrome瀏覽器也會(huì)有自己的cache烂叔。
dns cache除了好處以外谨胞,也帶來(lái)了其他問(wèn)題。比如dns cache可能被惡意病毒修改蒜鸡,將真實(shí)IP改成釣魚(yú)網(wǎng)站的IP胯努,對(duì)用戶(hù)進(jìn)行誘導(dǎo)和釣魚(yú)。還有在服務(wù)發(fā)現(xiàn)的這種特定場(chǎng)景下逢防,dns cache是不被允許的叶沛,會(huì)出現(xiàn)IP更新不及時(shí)導(dǎo)致API流量的損失和錯(cuò)誤,例如部署上線(xiàn)或者宕機(jī)忘朝,相比之下灰署,運(yùn)維響應(yīng)的時(shí)長(zhǎng)會(huì)造成更大的損失。但為了解決這個(gè)問(wèn)題,在client和server端中間增加一層代理溉箕,dns記錄指向這個(gè)代理晦墙。如圖:
代理職責(zé)一般有:
- 服務(wù)發(fā)現(xiàn),幫助客戶(hù)端發(fā)現(xiàn)有多少服務(wù)實(shí)例肴茄。
- 健康檢查晌畅,對(duì)服務(wù)實(shí)例進(jìn)行健康檢查,及時(shí)剔除不健康實(shí)例寡痰,避免流量的損失抗楔。并通過(guò)此機(jī)制完成服務(wù)的無(wú)損上線(xiàn)。
- 流量負(fù)載均衡拦坠。
代理一般分為:
類(lèi)別 | 名稱(chēng) |
---|---|
四層負(fù)載均衡 | LVS F5 |
七層負(fù)載均衡 | nginx openresty |
四層代理對(duì)外暴露的IP一般稱(chēng)為虛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
- 寫(xiě)個(gè)demo測(cè)試一下有無(wú)cache的性能區(qū)別:
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()
}
}
性能對(duì)比:
從對(duì)比中可看出:go的pure resolver因沒(méi)有cache和網(wǎng)絡(luò)不穩(wěn)定的因素连躏,總耗時(shí)較多。而cgo的resolver比較穩(wěn)定且耗時(shí)較低贞滨。
dns cache查看和清除
darwin
sudo killall -HUP mDNSResponder
linux(unix)
linux或類(lèi)unix系統(tǒng)是沒(méi)有操作系統(tǒng)級(jí)別的dns cache入热。除非安裝了dnsmasq或者
nscd(Name Service Caching Daemon),并開(kāi)啟疲迂。
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