如何在 pod 中做 golang 的 profiling

Posted by Luffyao on Saturday, March 7, 2020

前言

相比于 C++ 在 pod 中做 profiling, 那么对于云原生的 golang 来说就太方便了。下面我将讲述下我做 golang profiling 的具体过程和步骤。由于我们是基于 Restful 接口的系统设计,所以以下 profiling 都是基于 http/pprof 做的分析。

操作步骤

在代码中添加 handlers

例如:

// This is a function creating a HTTP2 server. and only registered profile and heap path,
// for others profiling path, you can add it according to yourself.
func profiling() {
    mux := http.NewServeMux()

    mux.HandleFunc("/debug/pprof/", pprof.Index)
    mux.HandleFunc("/debug/pprof/cmdline", pprof.Cmdline)
    mux.HandleFunc("/debug/pprof/profile", pprof.Profile)
    mux.HandleFunc("/debug/pprof/symbol", pprof.Symbol)
    mux.HandleFunc("/debug/pprof/trace", pprof.Trace)
    mux.HandleFunc("/debug/memstat", func(w http.ResponseWriter, r *http.Request) {

        var m runtime.MemStats
        runtime.ReadMemStats(&m)
        //fmt.Println(m)
        fmt.Printf("HeapSys %d, HeapAlloc %d, HeapIdle %d, HeapReleased%d,\n", m.HeapSys, m.HeapAlloc,
            m.HeapIdle, m.HeapReleased)
        //result := fmt.Sprintf("%v", m)
        w.WriteHeader(http.StatusOK)
        //w.Write([]byte(result))
    })

    h2s := &http2.Server{}

    httpServer := &http.Server{
        Addr:    ":10000",
        Handler: h2c.NewHandler(mux, h2s),
    }
    if err := httpServer.ListenAndServe(); err != nil {
        golog.Message(golog.Error, "Error while listening")
    }
}

// then in the main function, you can invoke it.
go profiling()

编译代码并更新到 pod 中

编译代码,重新创建 image,并更新到 deployment 里面。这里根据自己的环境进行部署。

暴露 pod 中的 server 的端口

// you can use kubectl port-forward --help to view detailed useage.

kubectl port-forward pods/yourpod port:port

NOTE: 这里需要注意一点,就是如果是添加的新的端口,需要在 deployment 中的 container.ports 下面加上。

load 测试

这里我用的是 h2load.

h2load -D 2 -c 10 -m 10 -H':method:POST' -H'content-type:application/json' your_restful_uri -d data.txt

Profiling 分析

你需要用 pprof 命令采集 sample, 然后对采集到的信息进行分析。

// more detailed command usage you can refer to https://golang.org/pkg/net/http/pprof/

go tool pprof http://localhost:9001/debug/pprof/profile 
go tool pprof -alloc_objects http://localhost:9001/debug/pprof/heap
go tool pprof  http://localhost:9001/debug/pprof/heap

如何进行分析,可以参考 diagnostics, 如果你不能打开官方文档,可以参考 performance optimization, 里面讲述了详细的 profiling 的使用。

火焰图分析

  1. 安装 go-torch

    go get github.com/uber/go-torch
    
  2. 安装 FlameGraph

    cd $WORK_PATH && git clone https://github.com/brendangregg/FlameGraph.git
    export PATH=$PATH:$WORK_PATH/FlameGraph
    
  3. 安装 graphviz

    sudo apt-get install graphviz(ubuntu)
    or 
    yum install graphviz(CentOS, Redhat)
    
  4. 使用

    go-torch -u http://localhost:8888/debug/pprof/ -p > profile-local.svg 
    

    然后浏览器打开生成的文件 profile-local.svg.

参考文章