prometheus与grafana的安装
grom接入Prometheus,grafana-CSDN博客
Prometheus 动态加载
我们想给Prometheus新增监听任务新增ginapp项目只需要在原来的配置文件下面新增ginapp相关metric

在docker compose文件下面新增

执行
docker-compose up -d
curl -X POST http://localhost:9090/-/reload
granfa配置新的job


配置golang dashboard模版


配置之后我们看以在dashboard看到

Gin框架中间件配置

package initialization
import (
"awesomeProject3/middware"
"awesomeProject3/router"
"github.com/Depado/ginprom"
"github.com/gin-gonic/gin"
_ "net/http/pprof"
)
func Routers() *gin.Engine {
r := gin.New()
r.Use(middware.GinRecovery(true), middware.GinZapLogger())
r.Use(middware.Cors())
router.InitOrderRouter(r)
p := ginprom.New(
ginprom.Engine(r),
ginprom.Subsystem("gin"),
)
r.Use(p.Instrument())
return r
}
pprof配置
package router
import (
"awesomeProject3/api"
"github.com/gin-gonic/gin"
"net/http"
"net/http/pprof"
)
func InitOrderRouter(Router *gin.Engine) {
Router.GET("/health", func(c *gin.Context) {
c.JSON(http.StatusOK, gin.H{
"code": http.StatusOK,
"success": true,
})
})
// 定义一个简单的GET路由
Router.GET("/v1/ping", func(c *gin.Context) {
c.JSON(http.StatusOK, gin.H{
"message": "pong",
})
})
Router.GET("/test", api.TestHandler) //
pprofGroup := Router.Group("/debug/pprof")
{
pprofGroup.GET("/", gin.WrapF(pprof.Index))
pprofGroup.GET("/cmdline", gin.WrapF(pprof.Cmdline))
pprofGroup.GET("/profile", gin.WrapF(pprof.Profile))
pprofGroup.GET("/symbol", gin.WrapF(pprof.Symbol))
pprofGroup.GET("/trace", gin.WrapF(pprof.Trace))
pprofGroup.GET("/allocs", gin.WrapH(pprof.Handler("allocs")))
pprofGroup.GET("/block", gin.WrapH(pprof.Handler("block")))
pprofGroup.GET("/goroutine", gin.WrapH(pprof.Handler("goroutine")))
pprofGroup.GET("/heap", gin.WrapH(pprof.Handler("heap")))
pprofGroup.GET("/mutex", gin.WrapH(pprof.Handler("mutex")))
pprofGroup.GET("/threadcreate", gin.WrapH(pprof.Handler("threadcreate")))
}
}
模拟内存泄露
之前我们生产项目中出现过一次严重的内存泄露,例子如下图所示,该接口qps非常高

对当前接口压测
pprof监控

Grafana监控

我们看到goroutine数量已经爆表了,我的mac风扇开始转了

这个时候可以点击pprof groutine很好定位哪一块出现了内存泄露

结论
我们在使用golang 高并行处理下游任务的时候,一定要对下游基础设施要有敬畏之心,调用时限制goroutine的运行数量并且设置上context超时控制,做好超时熔断措施,做好监控警告,下游基础设施如果达到瓶颈,我们可对下游基础进行主从 水平扩容等。