开启 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系统中,解析域名有两种选项:

  1. 使用纯Go解析器直接发送DNS请求给/etc/resolv.conf文件中的服务器
  2. 使用基于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"]