0x00 前言
0x01 DEBUG 汇总
调用图
- 安装
yum install graphviz
go tool pprof main http://localhost:8000/debug/pprof/heap
或者 goroutine,进入命令行- 输入
svg
命令即可保存
火焰图
- 安装
FlameGraph
,如下 - 安装
go-torch
,拿到bin
文件 - 使用命令
go-torch -u http://localhost:6060 -t 30
生成火焰图
git clone https://github.com/brendangregg/FlameGraph.git
cp FlameGraph/flamegraph.pl /usr/local/bin
0x02 一些经验之谈
关于调用图
一般调用图中高亮的部分就能告诉开发者是哪里发生了内存泄漏了(除非内存是预设的 size,如代码中本地初始化一块缓存)
部署与编译机器分开
比如,需要调试 goroutine,部署机器上通过 curl http://localhost:6060/debug/pprof/goroutine -o goroutine.pprof
保存运行时配置,然后将 goroutine.pprof
传输到编译机器上,通过 go tool pprof goroutine.pprof
即可进行调试
对比前后时间差异
导出时间点 A 的文件:
curl http://localhost:6060/debug/pprof/heap > heap.timeA
curl http://localhost1:6060/debug/pprof/goroutine> goroutine.timeA
导出时间点 B 的文件:
curl http://localhost:6060/debug/pprof/heap > heap.timeB
curl http://localhost1:6060/debug/pprof/goroutine> goroutine.timeB
对比两个时间点的堆栈差异:
go tool pprof --base heap.timeA heap.timeB
go tool pprof --http :8080 --base heap.timeA heap.timeB
调试goroutine profile的方法
# 下载cpu profile,默认从当前开始收集30s的cpu使用情况,需要等待30s
go tool pprof http://localhost:6060/debug/pprof/profile # 30-second CPU profile
go tool pprof http://localhost:6060/debug/pprof/profile?seconds=120 # wait 120s
# 下载heap profile
go tool pprof http://localhost:6060/debug/pprof/heap # heap profile
# 下载goroutine profile
go tool pprof http://localhost:6060/debug/pprof/goroutine # goroutine profile
# 下载block profile
go tool pprof http://localhost:6060/debug/pprof/block # goroutine blocking profile
# 下载mutex profile
go tool pprof http://localhost:6060/debug/pprof/mutex
对应采集到的pprof文件,最常用的就是下面三个命令:
top
:显示正运行到某个函数goroutine的数量traces
:显示所有goroutine的调用栈list
:列出代码详细的信息
traces命令
现网中,基于traces
命令可以协助排查并定位goroutine泄漏问题
curl http://localhost:6060/debug/pprof/goroutine> goroutine.timeH
go tool --pprof goroutine.timeH
#执行traces
参考下面的例子,结合项目分析,排名前面的goroutine数量是不正常的,存在goroutine泄漏问题:
runtime.gopark
方法的启示
若查看 goroutine 文件使用 traces
命令,发现大量的 runtime.gopark
函数调用,那么可以初步认定为程序存在 goroutine 泄漏。gopark
函数主要作用就是将当前的 goroutine 放入等待状态,这就意味着 goroutine 被暂时被搁置,也就是被运行时调度器暂停了
- 调用
acquirem
函数 - 获取当前 goroutine 所绑定的
m
,设置各类所需数据 - 调用
releasem
函数将当前 goroutine 和其m
的绑定关系解除 - 调用
park_m
函数 - 将当前 goroutine 的状态从
_Grunning
切换为_Gwaiting
,也就是等待状态 - 删除
m
和当前 goroutinem->curg
(简称gp
)之间的关联 - 调用
mcall
函数,仅会在需要进行 goroutiine 切换时会被调用 - 切换当前线程的堆栈,从
g
的堆栈切换到g0
的堆栈并调用fn(g)
函数 - 将
g
的当前 PC/SP 保存在g->sched
中,以便后续调用goready
函数时可以恢复运行现场
0x03 参考
FEATURED TAGS
Latex
gRPC
负载均衡
OpenSSH
Authentication
Consul
Etcd
Kubernetes
性能优化
Python
分布式锁
WebConsole
后台开发
Golang
OpenSource
Nginx
Vault
网络安全
Perl
分布式理论
Raft
正则表达式
Redis
分布式
限流
go-redis
微服务
反向代理
ReverseProxy
Cache
缓存
连接池
OpenTracing
GOMAXPROCS
GoMicro
微服务框架
日志
zap
Pool
Kratos
Hystrix
熔断
并发
Pipeline
证书
Prometheus
Metrics
PromQL
Breaker
定时器
Timer
Timeout
Kafka
Xorm
MySQL
Fasthttp
bytebufferpool
任务队列
队列
异步队列
GOIM
Pprof
errgroup
consistent-hash
Zinx
网络框架
设计模式
HTTP
Gateway
Queue
Docker
网关
Statefulset
NFS
Machinery
Teleport
Zero Trust
Oxy
存储
Confd
热更新
OAuth
SAML
OpenID
Openssl
AES
微服务网关
IM
KMS
安全
数据结构
hashtable
Sort
Asynq
基数树
Radix
Crontab
热重启
系统编程
sarama
Go-Zero
RDP
VNC
协程池
UDP
hashmap
网络编程
自适应技术
环形队列
Ring Buffer
Circular Buffer
InnoDB
timewheel
GroupCache
Jaeger
GOSSIP
CAP
Bash
websocket
事务
GC
TLS
singleflight
闭包
Helm
network
iptables
MITM
HTTPS
Tap
Tun
路由
wireguard
gvisor
Git
NAT
协议栈
Envoy
FRP
DPI
gopacket
Cgroup
Namespace
DNS
eBPF
GoZero
Gost
Clash
gopsutil
HIDS
ELKEID
XDP
TC
Linux