英文:
golang memory leak when break call net.LookupHost by time.After
问题
我使用这个函数来限制DNS服务器的响应时间。
func LookupHost(hostname string, timeout time.Duration) ([]string, error) {
c1 := make(chan []string)
c2 := make(chan error)
go func() {
var ipaddr []string
ipaddr, err := net.LookupHost(hostname)
if err != nil {
c2 <- err
close(c2)
}
c1 <- ipaddr
close(c1)
}()
select {
case ipaddr := <-c1:
return ipaddr, nil
case err := <-c2:
return []string{}, err
case <-time.After(timeout):
return []string{}, errors.New("timeout")
}
}
问题是这个函数会消耗内存。
我认为这是因为我中断了net.LookupHost(hostname)
系统调用。
有没有办法避免这个问题?
也许有其他方法可以设置带有超时的DNS服务器查询吗?
英文:
I use this function to limit response time from DNS server
func LookupHost(hostname string, timeout time.Duration) ([]string, error) {
c1 := make(chan []string)
c2 := make(chan error)
go func() {
var ipaddr []string
ipaddr, err := net.LookupHost(hostname)
if err != nil {
c2 <- err
close(c2)
}
c1 <- ipaddr
close(c1)
}()
select {
case ipaddr := <-c1:
return ipaddr, nil
case err := <-c2:
return []string{}, err
case <-time.After(timeout):
return []string{}, errors.New("timeout")
}
}
The problem is that this function eat memory.
I think it is because I break net.LookupHost(hostname)
syscall.
Any way to avoid this?
May be some other way how to query DNS servers with timeouts?
答案1
得分: 1
你可以查看bogdanovich/dns_resolver
中提出的另一种实现方式。
其中的dns_resolver.go
包含了超时管理。
resolver := dns_resolver.New([]string{"8.8.8.8", "8.8.4.4"})
// 或者
// resolver := dns_resolver.NewFromResolvConf("resolv.conf")
// 在发生I/O超时的情况下
resolver.RetryTimes = 5
然后,你可以将整个调用包装在一个goroutine中,以防止调用net.LookupHost()
时突然中断。
ip, err := resolver.LookupHost("google.com")
if err != nil {
log.Fatal(err.Error())
}
log.Println(ip)
// 输出 [216.58.192.46]
英文:
You can check an alternative implementation proposed in bogdanovich/dns_resolver
Its dns_resolver.go
does include timeout management
resolver := dns_resolver.New([]string{"8.8.8.8", "8.8.4.4"})
// OR
// resolver := dns_resolver.NewFromResolvConf("resolv.conf")
// In case of i/o timeout
resolver.RetryTimes = 5
You can then wrap the all call in a goroutine, in order for the call to not break abruptly net.LookupHost()
.
ip, err := resolver.LookupHost("google.com")
if err != nil {
log.Fatal(err.Error())
}
log.Println(ip)
// Output [216.58.192.46]
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论