我有一个用 Go 编写的相对较大的 Web 应用程序,它使用 Gorilla 的 mux 进行路由。 我最近意识到我的 Web 应用程序非常慢,我想分析 Web 应用程序。
看完之后,似乎net/http/pprof就是我需要的。 但我不能让它用复用器运行;即使在最微不足道的 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)
}
我的首选方法是让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)
}
}
我发现这种方法比依赖于隐藏初始化方法的实现的方法稳定得多,并且还可以保证您不会错过任何内容。
user983716 - 感谢您的问题和解决方案!
我无法使用 Web 索引 (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"))
}
...
如果有人有同样的问题,我希望这有所帮助!
对不起这个问题。 答案就在 pprof 的 init() 函数中。 只需将 4 个功能从 pprof
添加到多路复用路由器。 这是上面的固定代码。
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)
}
我做了别的事情,我在不同的端口上添加了另一个本机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
以前的例子对我这边并不真正有效。
要在现有的 golang 项目中使用 pprof 和 gorrila/mux,请尝试添加:
...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/
就是这样:
r := mux.NewRouter()
r.PathPrefix("/debug").Handler(http.DefaultServeMux)
我使用 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答案的结合。
以下方法应该有效:
import (
"net/http"
_ "net/http/pprof"
)
myrouter.PathPrefix("/debug/pprof/").Handler(http.DefaultServeMux)