Profiling使用Gorilla的mux和net / http / pprof构建的Go web应用程序

时间:2013-10-25 13:21:07

标签: go

我有一个用Go编写的相对较大的Web应用程序,它使用Gorilla's mux进行路由。我最近意识到我的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)
}

9 个答案:

答案 0 :(得分:20)

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"))
}

...

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

答案 1 :(得分:15)

我首选的方法是让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)
    }
}

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

答案 2 :(得分:12)

对不起那个问题。答案在pprof的init()函数中。只需要将pprof中的4个函数添加到mux路由器。以下是上面的固定代码。

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)
}

答案 3 :(得分:2)

以前的例子对我而言并不奏效。

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

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

然后转到http://localhost:6060/debug/pprof/

答案 4 :(得分:1)

我做了别的事情,我在另一个端口添加了另一个原生的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/并且applcation正在端口上运行:8080

答案 5 :(得分:1)

就这样:

r := mux.NewRouter()
r.PathPrefix("/debug").Handler(http.DefaultServeMux)

答案 6 :(得分: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答案的结合。

答案 7 :(得分:0)

以下方法应该起作用:

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

myrouter.PathPrefix("/debug/pprof/").Handler(http.DefaultServeMux)

答案 8 :(得分:0)

m.PathPrefix("/debug/pprof").Handler(http.DefaultServeMux)

这对我有用。