go开启pporf, 通过webui对服务进行诊断
go作为现代高级编程语言,无须程序员关心内存申请和释放,降低了入门门槛,但也导致很多水平良莠不齐的人写出很多不好的代码,导致服务出现各种各样不稳定的情况。如大对象的频繁申请和释放、协程泄露、指针断言反射的乱用等等。
虽然说代码是屎山,但是在服务尚且能用的情况下,架构师肯定没有精力来调教每行代码,这时候就可以通过pprof从宏观层面把脉服务的运行情况,从而找出那些脑残的代码来优化。
无论是用gin,还是go-zero, 亦或者net/http, 接入pprof都十分简单,只需要将pprof的几个handle函数注册到web框架的route里面即可,我们以go-zero为例
先定义一个profile.go文件
1package profile
2
3import (
4 "github.com/zeromicro/go-zero/rest"
5 "net/http"
6 "net/http/pprof"
7)
8
9func wrapH(h http.Handler) http.HandlerFunc {
10 return func(ResponseWriter http.ResponseWriter, Request *http.Request) {
11 h.ServeHTTP(ResponseWriter, Request)
12 }
13}
14
15func ProfileRoutes() []rest.Route {
16 pprofRoutes := make([]rest.Route, 0)
17 pprofRoutes = append(pprofRoutes, rest.Route{
18 Method: http.MethodGet,
19 Path: "/debug/pprof/",
20 Handler: pprof.Index,
21 })
22 pprofRoutes = append(pprofRoutes, rest.Route{
23 Method: http.MethodGet,
24 Path: "/debug/pprof/cmdline",
25 Handler: pprof.Cmdline,
26 })
27 pprofRoutes = append(pprofRoutes, rest.Route{
28 Method: http.MethodGet,
29 Path: "/debug/pprof/profile",
30 Handler: pprof.Profile,
31 })
32 pprofRoutes = append(pprofRoutes, rest.Route{
33 Method: http.MethodGet,
34 Path: "/debug/pprof/symbol",
35 Handler: pprof.Symbol,
36 })
37 pprofRoutes = append(pprofRoutes, rest.Route{
38 Method: http.MethodPost,
39 Path: "/debug/pprof/symbol",
40 Handler: pprof.Symbol,
41 })
42 pprofRoutes = append(pprofRoutes, rest.Route{
43 Method: http.MethodGet,
44 Path: "/debug/pprof/trace",
45 Handler: pprof.Trace,
46 })
47 pprofRoutes = append(pprofRoutes, rest.Route{
48 Method: http.MethodGet,
49 Path: "/debug/pprof/goroutine",
50 Handler: wrapH(pprof.Handler("goroutine")),
51 })
52 pprofRoutes = append(pprofRoutes, rest.Route{
53 Method: http.MethodGet,
54 Path: "/debug/pprof/heap",
55 Handler: wrapH(pprof.Handler("heap")),
56 })
57 pprofRoutes = append(pprofRoutes, rest.Route{
58 Method: http.MethodGet,
59 Path: "/debug/pprof/block",
60 Handler: wrapH(pprof.Handler("block")),
61 })
62 pprofRoutes = append(pprofRoutes, rest.Route{
63 Method: http.MethodGet,
64 Path: "/debug/pprof/mutex",
65 Handler: wrapH(pprof.Handler("mutex")),
66 })
67 pprofRoutes = append(pprofRoutes, rest.Route{
68 Method: http.MethodGet,
69 Path: "/debug/pprof/threadcreate",
70 Handler: wrapH(pprof.Handler("threadcreate")),
71 })
72 pprofRoutes = append(pprofRoutes, rest.Route{
73 Method: http.MethodGet,
74 Path: "/debug/pprof/allocs",
75 Handler: wrapH(pprof.Handler("allocs")),
76 })
77
78 return pprofRoutes
79}
之后在main中将这些routes加到server里面
1func main() {
2 ...
3
4 server := rest.MustNewServer(restConf)
5 defer server.Stop()
6
7 gen.Register(server)
8
9
10 // profile 性能分析
11 server.AddRoutes(profile.ProfileRoutes(), rest.WithTimeout(time.Second*35))
12
13 server.Start()
14}
这样程序启动之后就可以通过go tool pprof命令去在浏览器中查看服务的cpu、堆栈、协程的运行情况。
1go tool pprof -http=:1234 http://$server_ip:$server_port/debug/pprof/allocs
请确保自己的机器装了graphviz,这样就可以在浏览器中以图的方式来快速定位问题,以macos为例:
1brew install graphviz



评论列表:
暂无评论 😭