19

我有一个用 Go 编写的相对较大的 Web 应用程序,它使用Gorilla 的多路复用器进行路由。我最近意识到我的 web 应用程序很慢,我想分析 web 应用程序。

阅读后,似乎net/http/pprof是我需要的。但我不能让它与mux一起运行;即使是最简单的 Web 应用程序。

有谁知道如何使这项工作?

这是一个不起作用的琐碎代码的示例(即在 没有提供任何服务/debug)。

package main

import (
    "fmt"
    "github.com/gorilla/mux"
    "math"
    "net/http"
)
import _ "net/http/pprof"

func SayHello(w http.ResponseWriter, r *http.Request) {
    for i := 0; i < 1000000; i++ {
        math.Pow(36, 89)
    }
    fmt.Fprint(w, "Hello!")
}

func main() {
    r := mux.NewRouter()
    r.HandleFunc("/hello", SayHello)
    http.ListenAndServe(":6060", r)
}
4

8 回答 8

33

我首选的方法是让net/http/pprof自己注册到http.DefaultServeMux,然后传递所有以以下开头的请求/debug/pprof/

package main

import (
    "net/http"
    _ "net/http/pprof"

    "github.com/gorilla/mux"
)

func main() {
    router := mux.NewRouter()
    router.PathPrefix("/debug/pprof/").Handler(http.DefaultServeMux)
    if err := http.ListenAndServe(":6060", router); err != nil {
        panic(err)
    }
}

我发现这种方法比依赖于隐藏初始化方法的实现稳定得多,并且还保证你不会错过任何东西。

于 2015-10-20T16:08:46.067 回答
31

user983716 - 感谢您的问题和解决方案!

我无法使用来自网络索引 ( http://[my-server]/debug/pprof ) 的链接,直到我在您的解决方案中添加了几行,如下所示:

...

func AttachProfiler(router *mux.Router) {
    router.HandleFunc("/debug/pprof/", pprof.Index)
    router.HandleFunc("/debug/pprof/cmdline", pprof.Cmdline)
    router.HandleFunc("/debug/pprof/profile", pprof.Profile)
    router.HandleFunc("/debug/pprof/symbol", pprof.Symbol)

    // Manually add support for paths linked to by index page at /debug/pprof/
    router.Handle("/debug/pprof/goroutine", pprof.Handler("goroutine"))
    router.Handle("/debug/pprof/heap", pprof.Handler("heap"))
    router.Handle("/debug/pprof/threadcreate", pprof.Handler("threadcreate"))
    router.Handle("/debug/pprof/block", pprof.Handler("block"))
}

...

如果有人有同样的问题,我希望这会有所帮助!

于 2015-05-12T21:17:33.220 回答
13

对不起那个问题。答案在pprof的 init() 函数中。只需向pprof多路复用路由器添加 4 个功能。这是上面的固定代码。

package main

import (
    "fmt"
    "github.com/gorilla/mux"
    "math"

    "net/http"
)
import "net/http/pprof"

func AttachProfiler(router *mux.Router) {
    router.HandleFunc("/debug/pprof/", pprof.Index)
    router.HandleFunc("/debug/pprof/cmdline", pprof.Cmdline)
    router.HandleFunc("/debug/pprof/profile", pprof.Profile)
    router.HandleFunc("/debug/pprof/symbol", pprof.Symbol)
}

func SayHello(w http.ResponseWriter, r *http.Request) {
    for i := 0; i < 1000000; i++ {
        math.Pow(36, 89)
    }
    fmt.Fprint(w, "Hello!")
}

func main() {
    r := mux.NewRouter()
    AttachProfiler(r)
    r.HandleFunc("/hello", SayHello)
    http.ListenAndServe(":6060", r)
}
于 2013-10-25T13:35:22.010 回答
5

以前的例子对我来说并不适用。

要在现有的带有 gorrila/mux 的 golang 项目中使用 pprof,请尝试添加:

...previous code

func main() {
    r := mux.NewRouter()
    r.HandleFunc("/hello", SayHello)

    go func() {
        log.Fatal(http.ListenAndServe(":6061", http.DefaultServeMux))
    }()

    http.ListenAndServe(":6060", r)
}

然后去http://localhost:6061/debug/pprof/

于 2019-02-14T14:16:39.397 回答
4

我做了其他事情,我在不同的端口上添加了另一个本机 http 服务器,它开箱即用

package main

import (
    "fmt"
    "log"
    "net/http"

    _ "net/http/pprof"
)


func main() {
    go func() {
        log.Println(http.ListenAndServe(":6060", nil))
    }()
    log.Fatalln(http.ListenAndServe(":8080", route.Handlers()))
}

现在 pprof 端点位于: http://localhost:6060/debug/pprof/并且应用程序正在端口:8080 上运行

于 2015-11-30T14:09:25.653 回答
1

就这样:

r := mux.NewRouter()
r.PathPrefix("/debug").Handler(http.DefaultServeMux)
于 2016-08-09T07:16:01.717 回答
0

我正在使用https://github.com/julienschmidt/httprouter但我刚刚从谷歌搜索中得到了这个答案。这就是我所做的

router := httprouter.New()
router.Handler("GET", "/debug/pprof/profile", http.DefaultServeMux)
router.Handler("GET", "/debug/pprof/heap", http.DefaultServeMux)

我只需要这两条路线。这个答案是@damien 和@user983716 答案的结合。

于 2017-10-27T10:17:30.947 回答
0

以下应该有效:

import (
 "net/http"
 _ "net/http/pprof"
)

myrouter.PathPrefix("/debug/pprof/").Handler(http.DefaultServeMux)
于 2019-09-04T20:16:18.417 回答