Go 中的 HTTP 资源泄漏之谜

我喜欢排查泄露的问题。这是一个智力之谜,我总能在这个过程中学到新东西。

这个谜就像你在电视上读到或看的一样:细节是猥琐的,从不令人沮丧,最后,我们总能得到一个很好的合乎逻辑的解释。这就是计算机的伟大之处:它们最终是可以预测的,所以我可以安全地扮演侦探角色,因为我知道我总是能得到我的罪犯。

如果你讨厌推理小说或者只想学习参考,你可以跳到关键要点(剧透警告,咄

泄露 Dogfood

看似直线稳定的增长实际上是阶梯式的,尽管数据中有一些噪声,但我们似乎看到每 1 小时就有一个很大的增长。

事实证明,我们的 coderd 服务每 1 小时运行 4 个后台作业。我们有四名嫌疑人。会是哪一个呢会不止一个人干的我们进行侦察的一个快速修复方法是改变作业运行的周期。我可以一次只做一件任务,但如果我能做一点改变,就能留在原地,不是更好吗p>

选择 1 小时的间隔是大多数人认为的“一个不错的整数”。但与人不同的是,计算机不关心整数[2]。1 小时并不是我们所关心的确切值,因此可以将其更改为接近的值,而不期望系统范围的行为受到影响。

最好避免整数,事实上,整数越少越好。我选择了其中最不四舍五入的数:质数。这使得从数学上讲,周期不可能是更频繁的任务的倍数,所以它们不断地在同一时间发生。选择一个基本单位,然后让作业的质数乘以这个基本单位。我选择 1 分钟作为基本单位,这样就可以很容易地读出度量图表,因为我们的 Prometheus 指标每 15 秒左右才会被删除一次,所以比 1 分钟更小的度量并不能帮助我们理解度量。所以,1 小时的任务变成了47、53、59、67 分钟。

结果不言自明(google/go-containerregistry 仓库的一个 bug)。

关键要点

虽然每一个泄漏的代码都以自己的方式泄漏,但许多泄漏探测技术和分析工具都是通用的。

  1. 监控你的服务是否存在泄漏。检查每个 Go 软件的关键资源包括:a.内存 b.协程 c.文件描述符(打开的文件)

  2. 根据你的应用程序,你可能还需要监视:a.磁盘空间 b.Inodes c.子进程 d.应用程序使用的特殊资源(IP地址/p>

  3. 看看资源泄漏的速度:a.速率与负载相关吗与你的服务的请求路径相关 b.速率是否与负载无关是一份后台任务

  4. 避免在完全相同的时间间隔上运行所有后台作业。使用素数以避免作业运行重叠。

  5. 使用监控或日志记录后台作业的开始和结束时间;寻找这些时间和泄漏之间的相关性。

  6. 如果可以,可以导出或克隆真实数据,在 IDE 中重现问题。

最后一点,请注意:

克隆包含外部客户或用户数据的生产数据时要小心。如果你完全不确定,请在复制数据之前咨询你的安全团队。如果你在受监管的行业(金融、医疗保健等)经营或者是爬虫,情况就更是如此。

附注:

[1] 使用你自己的产品通俗地称为 dogfooding,如“吃你自己的狗粮”。

[2] 不同人对什么是圆形有不同的看法。

相关链接:

关键要点:https://coder.com/blog/go-leak-mysteries#key-takeaways

pprof HTTP端点:https://pkg.go.dev/net/http/pprof

代码阅读:https://github.com/golang/go/blob/8ed0e51b5e5cc50985444f39dc56c55e4fa3bcf9/src/net/http/transport.go#L98

挂在 readLoop goroutines 上的那一行:https://github.com/golang/go/blob/8ed0e51b5e5cc50985444f39dc56c55e4fa3bcf9/src/net/http/transport.go#L2213

都在等待新的 HTTP 请求:https://github.com/golang/go/blob/8ed0e51b5e5cc50985444f39dc56c55e4fa3bcf9/src/net/http/transport.go#L2392

go race检测器:https://go.dev/blog/race-detector

开始泄露的goroutines的行:https://github.com/golang/go/blob/8ed0e51b5e5cc50985444f39dc56c55e4fa3bcf9/src/net/http/transport.go#L1750

涉及许多 HTTP 请求的复杂交互:https://docs.docker.com/docker-hub/api/latest/

修复的PR:https://docs.docker.com/docker-hub/api/latest/

原文地址:

https://coder.com/blog/go-leak-mysteries

Spike Curtis

https:/github.com/gocn/translator/blob/master/2022/w46_HTTP_Resource_Leak_Mysteries_in_Go.md

译者:Jancd

往期推荐

免费!让Https证书不再成为烦恼

分享、在看与点赞Go 

d85e94d844ee8032cc5a2dc433a51e71.gif

文章知识点与官方知识档案匹配,可进一步学习相关知识 络技能树首页概览22992 人正在系统学习中

声明:本站部分文章及图片源自用户投稿,如本站任何资料有侵权请您尽早请联系jinwei@zod.com.cn进行处理,非常感谢!

上一篇 2022年10月16日
下一篇 2022年10月16日

相关推荐