如何精确定位挂起的函数

问题描述 投票:0回答:1

我有一个简单的golang程序:

package main

import (
    "fmt"
    "net/http"
    _ "net/http/pprof"
    "os/exec"
)

func bar() {
    // wait 5 seconds
    cmd := exec.Command("sleep", "5")
    err := cmd.Run()
    if err != nil {
        panic(err)
    }
}

func fooHandler(w http.ResponseWriter, r *http.Request) {
    bar()
    fmt.Fprintf(w, "Hello, world!")
}

func main() {
    http.HandleFunc("/foo", fooHandler)
    http.ListenAndServe(":8080", nil)
}

我想做的就是使用 golang 的跟踪功能来查明导致 5 秒延迟的函数。但是,我不知道该怎么做。

我已经跑了

curl -o trace.out http://localhost:8080/debug/pprof/trace?seconds=20

然后到达

/foo
端点。这会生成一个
trace.out
,我可以使用
go tool trace trace.out
查看它。我可以看到这个:

事实上,在 9 秒标记左右,我可以在可视化工具中看到一个线程花了 5 秒才能完成,但我似乎找不到如何获取堆栈跟踪或可以以某种方式向我指出

bar()
的事实罪魁祸首一直在耗尽。我在这里使用了错误的工具吗?

go trace pprof
1个回答
0
投票

您有几个选择:

  1. 使用
    runtime/trace
  2. 定义自定义跟踪区域
  3. 使用
    golang.org/x/net/trace
    并使用实时可视化工具

如果您想使用事实上的

go tool trace
/dominikh/gotraceui
挖掘痕迹的方法,那么选项 1 是最好的。

选项 2 启动很快,但我没有在示例程序之外使用过它。以下是我们如何将其连接到您的示例上:

package main

import (
    "context"
    "fmt"
    "net/http"
    _ "net/http/pprof"
    "os/exec"

    "golang.org/x/net/trace"
)

func bar(ctx context.Context) {
    tr, _ := trace.FromContext(ctx)
    tr.LazyPrintf("bar")

    cmd := exec.Command("sleep", "5")
    err := cmd.Run()
    if err != nil {
        panic(err)
    }
}

func fooHandler(w http.ResponseWriter, r *http.Request) {
    tr := trace.New("foo", r.URL.Path)
    defer tr.Finish()

    ctx := trace.NewContext(r.Context(), tr)
    bar(ctx)

    fmt.Fprintf(w, "Hello, world!")
}

func main() {
    // This pulls in /debug/requests and /debug/events
    mux := http.DefaultServeMux

    mux.HandleFunc("/foo", fooHandler)
    http.ListenAndServe(":8080", mux)
}

/foo
发出请求后,我们可以在浏览器中打开
localhost:8080/debug/requests
看到以下内容:

© www.soinside.com 2019 - 2024. All rights reserved.