Golang Go语言中 DNS 查询时 pure Go resolver 和 cgo resolver 耗时相差很大的原因

发布于 1周前 作者 itying888 来自 Go语言

Golang Go语言中 DNS 查询时 pure Go resolver 和 cgo resolver 耗时相差很大的原因

我昨天在这里提了一个问题Golang 中 http.Get 的耗时比 curl 耗时大很多是什么原因?, V 友@zeyexe已经帮我解答了问题(太强了!),他说应该是 Golang 的 net 库中的不同resolver导致的差异。不同耗时可能是 Windows 默认走系统调用,可能有 cache 加速。

今天想了下,即使是 cache 也不可能带来 pure Go resolver 和 cgo resolver 20s 左右的差异,就又花时间仔细探索了一下。

探索过程记录在我的博客里了,限于篇幅,在这儿直接说我最后发现的原因:

Go 版本 DNS 查询(pure Go resolver)在 Go 1.11 中出现了一个 bug(之前的版本没有这个 bug):不能正确处理/etc/resolv.conf中有 nameserver 不工作时的情形,不能“ fail fast ”,导致 timeout。这个 bug 经过 Go 开发人员在#133675#138175的讨论,已经在这个commit中修复,更新到 Go 1.11.1 就没有这个问题了。

至于更细节的这个 bug 是怎么出现的,又是怎么修好的。我就不再探索了,毕竟,我只是一个刚看到《 The Go Programming Language 》第一章的小白:sweat_smile:。


更多关于Golang Go语言中 DNS 查询时 pure Go resolver 和 cgo resolver 耗时相差很大的原因的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html

7 回复

, 因为话有点多,我就新开了一个帖子,没有在原贴中回复。再次感谢大佬的远程 debug,😁

更多关于Golang Go语言中 DNS 查询时 pure Go resolver 和 cgo resolver 耗时相差很大的原因的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


嚯,厉害呀,摸到了官方 BUG🤣

,哈,摸到最后是有点震惊。说起来这帖子几乎没人评论。。沉了的第一天伤心了一会儿 23333

这个其实也不是 BUG,是“ Feature ”,Windows 下的 DNS 查询确实有些复杂,curl、ping、nslookup 等工具用的都不是同一套 ns 机制, 这个问题在 windows 下多网卡的时候尤其明显,三个命令由于系统的“智能” DNS 导致查询使用的是不同网卡的 DNS 和流量出口

,^_^;你再细看看,问题和 Windows 没关系的。刚开始的猜测涉及到 Windows,但最终发现和 Windows 的机制没关系。(事实上这个问题干脆不能在 Windows 下复现)
不过谢谢你的解释了~

🌚可能是有点瞎,看到上面说 windows 以为是在 windows 开发,不过这个 smartdns 确实是存在于 windows 且会发生和这个问题类似的情况

在Golang中,DNS查询时pure Go resolver和cgo resolver耗时相差很大的原因,主要可以从以下几个方面来解释:

  1. 实现机制

    • pure Go resolver:完全使用Go语言实现,从/etc/resolv.conf中读取DNS服务器地址,并通过发送UDP报文来进行DNS查询。
    • cgo resolver:使用cgo调用C标准库的getaddrinfogetnameinfo函数来进行DNS解析,这种方式会涉及到系统线程的阻塞。
  2. 性能差异

    • pure Go resolver通常更高效,因为它只消耗一个Go协程,并且可以在Go的运行时系统中更好地集成。
    • cgo resolver可能会更慢,因为它会阻塞一个系统线程,且与系统C库的交互可能引入额外的开销。
  3. 使用场景

    • Go语言默认使用pure Go resolver,因为它提供了更好的性能和并发性。
    • 在某些特定条件下,如操作系统限制或环境变量设置等,Go语言可能会使用cgo resolver。

综上所述,pure Go resolver和cgo resolver在Golang中的DNS查询耗时差异主要源于它们的实现机制、性能差异以及使用场景的不同。为了优化DNS查询性能,建议尽可能使用pure Go resolver。

回到顶部