开启 DNS 缓存
- 当前 GO SDK 总是会去请求 DNS 服务器,而没有使用到 nscd 的缓存,可以通过导出环境变量GODEBUG=netdns=cgo,或者go build编译时指定参数-tags 'netcgo'控制读取 nscd 缓存。
测试
package main
import (
"net/http"
"os"
)
func main() {
http.DefaultClient.Get(os.Args[1])
}
go build -o goCli t.go
strace ./goCli https://i.cnblogs.com/ # 在输出结果中无法找到相关nscd关键字
① 使用GODEBUG=netdns=cgo
export GODEBUG=netdns=cgo
strace ./goCli https://i.cnblogs.com/ # 在输出结果中可以找到相关nscd关键字
② 使用-tags 'netcgo'
go build -tags 'netcgo' -o goCli t.go
strace ./goCli https://i.cnblogs.com/ # 在输出结果中可以找到相关nscd关键字
为什么netcgo会走nscd缓存
在golang官网中对net包(http://golang.org/pkg/net)关于域名解析有如下解释:
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.
大致意思是,在Unix系统中,解析域名有两种选项:
- 使用纯Go解析器直接发送DNS请求给/etc/resolv.conf文件中的服务器
- 使用基于CGo的解析器调用C库程序,例如getaddrinfo和getnameinfo
Dockerfile
FROM golang:alpine
ENV GO111MODULE=on \
CGO_ENABLED=0 \
GOOS=linux \
GOARCH=amd64 \
GOPROXY="https://goproxy.cn,direct"
WORKDIR /slb_exporter
COPY ./ ./
RUN go mod tidy && go build -o app
FROM busybox
EXPOSE 9202
COPY --from=0 /etc/ssl/certs /etc/ssl/certs
COPY --from=0 /slb_exporter/app .
ENTRYPOINT ["./app"]