『每周译Go』定位并修复 Go 中的内存泄漏

本文详细介绍了如何发现和修复Go语言中的内存泄漏问题,通过分析云服务客户端基础库的内存使用情况,找出由于未关闭gRPC客户端导致的内存泄漏。通过添加适当的关闭操作并自动化修复大量示例代码,避免了类似问题的发生。同时讨论了客户端管理、内存泄漏预防和改进库设计的策略。
摘要由CSDN通过智能技术生成

这篇文章回顾了我是如何发现内存泄漏、如何修复它、如何修复 Google 中的 Go 示例代码中的类似问题,以及我们是如何改进我们的基础库防止未来再次发生这种情况。

Google 云的 Go 的客户端基础库(https://github.com/googleapis/google-cloud-go)通常在底层使用 gRPC 来连接 Google 云的接口。当你创建一个客户端时,库会初始化一个与该 接口的连接,然后让这个连接保持打开状态,直到你在该客户端上调用 Close 操作。

client, err := api.NewClient()
// Check err.
defer client.Close()

客户端并发地使用是安全的,所以应该在使用完之前保留同一个客户端。但是,如果在应该关闭客户端的时候而没有关闭,会发生什么呢?

你会得到一个内存泄漏:底层连接从未被释放过。

Google 有一堆的 GitHub 自动化机器人,帮助管理数以百计的 GitHub 仓库。我们的一些机器人通过云上运行的(https://cloud.google.com/run/docs/quickstarts/build-and-deploy/go)上的Go 服务(https://github.com/googleapis/repo-automation-bots/tree/main/serverless-scheduler-proxy)代理它们的请求。我们的内存使用情况看起来就是典型的锯齿状内存泄漏情况。

我通过在程序中添加 pprof.Index 开始调试:

mux.HandleFunc("/debug/pprof/", pprof.Index)

pprof 提供运行时的分析数据,比如内存使用量。访问 Go 官方博客中的 分析 Go 程序(https://blog.golang.org/pprof)获取更多信息.

然后,我在本地构建并启动了该服务:

$ go build
$ PROJECT_ID=my-project PORT=8080 ./serverless-scheduler-proxy

然后,我向这个服务发送了一些构造的请求:

for i in {1..5}; do
curl --header "Content-Type: application/json" --request POST --data '{"name": "HelloHTTP", "type": "testing", "location": "us-central1"}' localhost:8080/v0/cron
echo " -- $i"
done

具体的负载和路径是针对我们服务的,与本文无关。为了获取一个关于内存使用情况的基线数据,我收集了一些初始的 pprof 数据。

curl http://localhost:8080/debug/pprof/heap > heap.0.pprof

通过检查输出的结果,可以看到一些内存的使用情况,但并没有发现徒增的问题(这很好!因为我们刚刚启动服务!)。

$ go tool pprof heap.0.pprof
F
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值