无法在现有服务器上使用go tool pprof。

huangapple go评论108阅读模式
英文:

Can't use go tool pprof with an existing server

问题

我有一个现有的HTTP服务器,我想对其进行性能分析。我已经在导入中包含了_ "net/http/pprof",并且我已经运行了HTTP服务器:

  1. router := createRouter()
  2. server := &http.Server {
  3. Addr: ":8080",
  4. Handler: router,
  5. ReadTimeout: 15*time.Second,
  6. WriteTimeout: 15*time.Second,
  7. // MaxHeaderBytes: 4096,
  8. }
  9. log.Fatal(server.ListenAndServe())

当我尝试访问http://localhost:8080/debug/pprof/时,我得到了404页面未找到的错误。

这是在本地机器上使用go tool pprof时的输出:

  1. userver@userver:~/Desktop/gotest$ go tool pprof http://192.168.0.27:8080/
  2. Use of uninitialized value $prefix in concatenation (.) or string at /usr/lib/go/pkg/tool/linux_amd64/pprof line 3019.
  3. Read http://192.168.0.27:8080/pprof/symbol
  4. Failed to get the number of symbols from http://192.168.0.27:8080/pprof/symbol
  5. userver@userver:~/Desktop/gotest$ go tool pprof http://localhost:8080/debug/pprof/profile
  6. Read http://localhost:8080/debug/pprof/symbol
  7. Failed to get the number of symbols from http://localhost:8080/debug/pprof/symbol

对于远程客户端也是一样的:

  1. MacBookAir:~ apple$ go tool pprof http://192.168.0.27:8080/
  2. Use of uninitialized value $prefix in concatenation (.) or string at /usr/local/Cellar/go/1.3.2/libexec/pkg/tool/darwin_amd64/pprof line 3027.
  3. Read http://192.168.0.27:8080/pprof/symbol
  4. Failed to get the number of symbols from http://192.168.0.27:8080/pprof/symbol
英文:

I have an existing http server which I would like to profile. I have included _ "net/http/pprof" to my imports, and I already have http server running:

  1. router := createRouter()
  2. server := &http.Server {
  3. Addr: ":8080",
  4. Handler: router,
  5. ReadTimeout: 15*time.Second,
  6. WriteTimeout: 15*time.Second,
  7. // MaxHeaderBytes: 4096,
  8. }
  9. log.Fatal(server.ListenAndServe())

When I'm trying to access http://localhost:8080/debug/pprof/ I get 404 page not found.

That's what I get when using go tool pprof on a local machine:

  1. userver@userver:~/Desktop/gotest$ go tool pprof http://192.168.0.27:8080/
  2. Use of uninitialized value $prefix in concatenation (.) or string at /usr/lib/go/pkg/tool/linux_amd64/pprof line 3019.
  3. Read http://192.168.0.27:8080/pprof/symbol
  4. Failed to get the number of symbols from http://192.168.0.27:8080/pprof/symbol
  5. userver@userver:~/Desktop/gotest$ go tool pprof http://localhost:8080/debug/pprof/profile
  6. Read http://localhost:8080/debug/pprof/symbol
  7. Failed to get the number of symbols from http://localhost:8080/debug/pprof/symbol

Same for a remote client:

  1. MacBookAir:~ apple$ go tool pprof http://192.168.0.27:8080/
  2. Use of uninitialized value $prefix in concatenation (.) or string at /usr/local/Cellar/go/1.3.2/libexec/pkg/tool/darwin_amd64/pprof line 3027.
  3. Read http://192.168.0.27:8080/pprof/symbol
  4. Failed to get the number of symbols from http://192.168.0.27:8080/pprof/symbol

答案1

得分: 29

net/http/pprof在文档中没有明确提到,但它只会将处理程序注册到http.DefaultServeMux中。

源代码中可以看到:

  1. func init() {
  2. http.Handle("/debug/pprof/", http.HandlerFunc(Index))
  3. http.Handle("/debug/pprof/cmdline", http.HandlerFunc(Cmdline))
  4. http.Handle("/debug/pprof/profile", http.HandlerFunc(Profile))
  5. http.Handle("/debug/pprof/symbol", http.HandlerFunc(Symbol))
  6. http.Handle("/debug/pprof/trace", http.HandlerFunc(Trace))
  7. }

如果你没有使用默认的mux,你只需要在你使用的mux中注册你想要的任何/所有处理程序,例如:mymux.HandleFunc("...", pprof.Index)等等。

或者,你可以使用默认的mux在一个单独的端口上进行监听(如果需要,也可以只绑定到本地主机),就像你展示的那样。

英文:

It's not explicitly mentioned in the documentation, but net/http/pprof only registers its handlers with http.DefaultServeMux.

From the source:

  1. func init() {
  2. http.Handle("/debug/pprof/", http.HandlerFunc(Index))
  3. http.Handle("/debug/pprof/cmdline", http.HandlerFunc(Cmdline))
  4. http.Handle("/debug/pprof/profile", http.HandlerFunc(Profile))
  5. http.Handle("/debug/pprof/symbol", http.HandlerFunc(Symbol))
  6. http.Handle("/debug/pprof/trace", http.HandlerFunc(Trace))
  7. }

If you're not using the default mux you just have to register any/all of those you want with whatever mux you're using, e.g. something like mymux.HandleFunc("…", pprof.Index), etc.

Alternatively you can listen on a separate port (also possibly bound to only localhost if desired) with the default mux as you've shown.

答案2

得分: 16

如果你正在使用github.com/gorilla/mux.Router,你可以将以/debug/为前缀的任何请求交给http.DefaultServeMux处理。

  1. import _ "net/http/debug"
  2. router := mux.NewRouter()
  3. router.PathPrefix("/debug/").Handler(http.DefaultServeMux)
英文:

If you're using a github.com/gorilla/mux.Router you can simply hand off any request prefixed with /debug/ to the http.DefaultServeMux.

  1. import _ "net/http/debug"
  2. router := mux.NewRouter()
  3. router.PathPrefix("/debug/").Handler(http.DefaultServeMux)

答案3

得分: 14

看起来问题出在我在http.Server实例中使用的github.com/gorilla/mux中的*mux.Router上的Handler

解决方案:只需再启动一个服务器用于pprof

  1. server := &http.Server {
  2. Addr: ":8080",
  3. Handler: router,
  4. ReadTimeout: 15*time.Second,
  5. WriteTimeout: 15*time.Second,
  6. }
  7. go func() {
  8. log.Println(http.ListenAndServe(":6060", nil))
  9. }()
  10. log.Fatal(server.ListenAndServe())
英文:

Looks like the problem was in a *mux.Router used from github.com/gorilla/mux which I used as a Handler in my http.Server instance.

Solution: just launch one more server just for the pprof:

  1. server := &http.Server {
  2. Addr: ":8080",
  3. Handler: router,
  4. ReadTimeout: 15*time.Second,
  5. WriteTimeout: 15*time.Second,
  6. }
  7. go func() {
  8. log.Println(http.ListenAndServe(":6060", nil))
  9. }()
  10. log.Fatal(server.ListenAndServe())

答案4

得分: 3

以下是如何将pprof与Gorilla mux结合使用的方法。为了避免HTTP 404错误,我们需要显式指定**/debug/pprof/{cmd}**的路由,因为Gorilla不会进行前缀路由:

  1. router := mux.NewRouter()
  2. router.Handle("/debug/pprof/", http.HandlerFunc(pprof.Index))
  3. router.Handle("/debug/pprof/cmdline", http.HandlerFunc(pprof.Cmdline))
  4. router.Handle("/debug/pprof/profile", http.HandlerFunc(pprof.Profile))
  5. router.Handle("/debug/pprof/symbol", http.HandlerFunc(pprof.Symbol))
  6. router.Handle("/debug/pprof/trace", http.HandlerFunc(pprof.Trace))
  7. router.Handle("/debug/pprof/{cmd}", http.HandlerFunc(pprof.Index)) // Gorilla mux的特殊处理
  8. err := http.ListenAndServe("127.0.0.1:9999", router)
  9. log.Errorf("pprof server listen failed: %v", err) // 注意:http.ListenAndServe永远不会返回nil

你可以在这里找到Gorilla mux的更多示例。

英文:

Here's how to use pprof in combination with Gorilla mux. To avoid HTTP 404 errors we need to explicitly specify the route for /debug/pprof/{cmd} because Gorilla doesn't do prefix routing:

  1. router := mux.NewRouter()
  2. router.Handle("/debug/pprof/", http.HandlerFunc(pprof.Index))
  3. router.Handle("/debug/pprof/cmdline", http.HandlerFunc(pprof.Cmdline))
  4. router.Handle("/debug/pprof/profile", http.HandlerFunc(pprof.Profile))
  5. router.Handle("/debug/pprof/symbol", http.HandlerFunc(pprof.Symbol))
  6. router.Handle("/debug/pprof/trace", http.HandlerFunc(pprof.Trace))
  7. router.Handle("/debug/pprof/{cmd}", http.HandlerFunc(pprof.Index)) // special handling for Gorilla mux
  8. err := http.ListenAndServe("127.0.0.1:9999", router)
  9. log.Errorf("pprof server listen failed: %v", err) // note: http.ListenAndServe never returns nil

huangapple
  • 本文由 发表于 2015年6月1日 02:09:26
  • 转载请务必保留本文链接:https://go.coder-hub.com/30560859.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定