内存泄漏
因一次线上内存泄漏问题的总结 go 内存泄漏大概有一下几种情况 长期存活的对象:如果某些对象的生命周期较长,但在使用完之后没有被正确释放,这些对象将一直保留在内存中,导致内存泄漏。 协程泄漏:在 Go 中,每个协程(goroutine)都是轻量级的并发执行单元。如果你启动了太多的协程并且没有适时关闭或终止它们,那么这些协程就会一直存在并占用内存,导致内存泄漏。 循环引用:如果存在对象之间的循环引用关系,即两个或多个对象相互引用,而没有其他的引用指向它们,这将阻止垃圾回收器回收这些对象,导致内存泄漏。 意外的全局变量引用:如果你在函数中意外保留了对全局变量的引用,即使函数执行完毕,这个函数所涉及的内存也无法释放,导致内存泄漏。 未关闭的文件或网络连接:如果在读写文件、网络通信或数据库连接等操作后,忘记关闭这些资源,将会导致系统资源泄漏,最终影响内存的使用。 不正确的缓存管理:当使用缓存来存储数据时,如果没有合适地管理缓存的大小和生命周期,可能会导致过多的对象一直存在于缓存中而无法被释放,从而引发内存泄漏。 未正确使用释放资源的函数:在使用第三方库或 API 时,如果没有按照正确的方式使用和释放资源,比如数据库连接或操作系统句柄等,将导致资源泄漏,可能会间接导致内存泄漏。 这次出问题的是未关闭网络连接(集群内其他服务)没有关闭http Response.Body,导致这两个程序内存一直增长,一个服务内存泄漏导致另一个服务goroutine无法释放,到达k8s内存上限被kill掉 排查方法 通过代码pprof抓取相应数据 导入net/http/pprof自动注册内置好的处理方法,开启默认http服务 我们主要看第二种,第一种可以自己看net/http/pprof里面的写法或者参考文档 用浏览器查看http[s]://xxx/debug/pprof页面,一共有如下几个指标 allocs: 内存过往统计,可以看运行过程中哪些过程使用内存最多 block: 看有哪些被阻塞了,比如各种io cmdline: 运行程序时的名称和参数 比如`./app a b c` goroutine: goroutine信息 heap: 在用堆内存信息 mutex: 锁信息 profile: CPU信息 threadcreate: 系统线程创建信息 trace: 追踪信息,比如GC, 各个goroutine调度等 其中allocs/block/goroutine/heap/mutex/profile 都可以使用go tool pprof -http=":8080" http[s]://host:port/debug/pprof/xxxxx(其中xxxxx用前面几种指标代替) 查看详细信息 trace需要先点击trace下载,然后使用go tool trace tracefile来查看