传统检测内存泄露可以看一下我这篇文章Gin框架接入Prometheus,grafana辅助pprof检测内存泄露-CSDN博客
pyroscope被Grafana收购,GPT来总结一下pyroscope的强大之处🐶
pyroscope github地址
pyroscope与grafana的安装
docker compose安装,这里我们其实可以不使用grafana,pyroscope已经是一个很完整的产品,但是我们在grafana里面可以配置数据源,也可以在grafana里面查看,grafana暂时还没有好的pyroscope dashboard
version: '3.8'
services:
grafana:
image: grafana/grafana
container_name: grafana
ports:
- "3000:3000"
networks:
- monitoring
depends_on:
- prometheus
pyroscope:
image: grafana/pyroscope
container_name: pyroscope
ports:
- "4040:4040"
networks:
- monitoring
networks:
monitoring:
driver: bridge
执行
docker-compose up -d
访问Pyroscope http://localhost:4040/ 我们可以看到go语言的各种性能指标与pprof检测的各类指标差不多
Gin框架中间件配置
我们在gin框架中间件中集成这个检测插件
ApplicationName: "simple.golang.app.golang",用于在Pyroscope筛选服务
package initialization
import (
"awesomeProject3/middware"
"awesomeProject3/router"
"github.com/Depado/ginprom"
"github.com/gin-gonic/gin"
"github.com/grafana/pyroscope-go"
_ "net/http/pprof"
"runtime"
)
func Routers() *gin.Engine {
r := gin.New()
r.Use(p.Instrument())
runtime.SetMutexProfileFraction(5)
runtime.SetBlockProfileRate(5)
pyroscope.Start(pyroscope.Config{
ApplicationName: "simple.golang.app.golang",
// replace this with the address of pyroscope server
ServerAddress: "http://localhost:4040",
// you can disable logging by setting this to nil
Logger: pyroscope.StandardLogger,
// you can provide static tags via a map:
Tags: map[string]string{"hostname": "ginapp"},
ProfileTypes: []pyroscope.ProfileType{
// these profile types are enabled by default:
pyroscope.ProfileCPU,
pyroscope.ProfileAllocObjects,
pyroscope.ProfileAllocSpace,
pyroscope.ProfileInuseObjects,
pyroscope.ProfileInuseSpace,
// these profile types are optional:
pyroscope.ProfileGoroutines,
pyroscope.ProfileMutexCount,
pyroscope.ProfileMutexDuration,
pyroscope.ProfileBlockCount,
pyroscope.ProfileBlockDuration,
},
})
return r
}
模拟内存泄露
我们来模拟内存泄露 对下面接口压测,压测粒度小一点,来看pyroscope的作用。
我们生产项目中出现过一次严重的内存泄露,例子如下图所示,该接口qps非常高
pyroscope监控查看内存泄露
我们点击Single可以看到详细的火焰图以及性能瓶颈,内存泄露的方法集代码,也就是产生goroutine泄露的地方
结论
我们在使用golang 高并行处理下游任务的时候,一定要对下游基础设施要有敬畏之心,调用时限制goroutine的运行数量并且设置上context超时控制,做好超时熔断措施,做好监控警告,下游基础设施如果达到瓶颈,我们可对下游基础进行主从 水平扩容等。