Welcome to my blog
Golang 服务内存泄漏问题分析一例
调查过程记录和分析 20200824 更新 20210219 更新 ref 调查过程记录和分析 记录下这个问题是因为这不同于传统典型的 Go 服务内存泄漏。 2020年8月15日前后,钉钉监控告警群不定时出现服务机器内存占用超 80% 告警,一开始以为是 Prometheus exporter 堆积造成的,准备下掉 Prometheus exporter 的集成代码,后来觉 得这个堆积速度太快了点,不到一天就吃掉 6GB,十分夸张,所以有空的时候用 gops 快照了 一下,内存情况如下图 (pprof) /app/bin # gops memstats 1 alloc: 54.66MB (57317968 bytes) total-alloc: 186.21GB (199938346560 bytes) sys: 6.72GB (7215977904 bytes) lookups: 0 mallocs: 2906600570 frees: 2906521966 heap-alloc: 54.66MB (57317968 bytes) heap-sys: 6.44GB (6909984768 bytes) heap-idle: 6.38GB (6846406656 bytes) heap-in-use: 60.63MB (63578112 bytes) heap-released: 6.33GB (6794371072 bytes) heap-objects: 78604 stack-in-use: 2....
集成 gops 的 go-micro 服务后 AfterStop 自定义函数不会执行的问题分析
前情提要 问题描述 分析原因 容器停止这个操作到底执行的是什么? go-micro 如何处理 linux signal? 经过二分法代码测试检查,发现进程 gops 后的问题 解决方案 经验总结 遇到一个很有意思的问题,在此记录一下。 TLDR: golang 服务通过 signal.Notify 注册 signal handler 的行为有且只有一次,否则会出现不可预知的行为。前情提要 公司开发微服务用的 go-micro 框架,这个框架提供了一个及其有价值的特性:micro.AfterStop 函数允许服务退出之后执行一段自定义的逻辑,通常用于清理资源,等待 goroutine 退出等。 另一方面,我们在生产环境也对每个服务集成了 gops ,这个工具极大了提升了服务的可观察性。 问题描述 某天,某位细心的同事告知 micro.AfterStop 自定义函数在容器重启时,并没有执行。现场复现确认问题存在。 下面是一个 minimal reproducible example package main import ( "fmt" "log" "github.com/micro/go-micro/v2" grpcServer "github.com/micro/go-micro/v2/server/grpc" "github.com/google/gops/agent" ) func main() { if err := agent.Listen(agent.Options{ Addr: "0.0.0.0:0", ShutdownCleanup: true}); err != nil { log....