英文:
Can't use go tool pprof with an existing server
问题
我有一个现有的HTTP服务器,我想对其进行性能分析。我已经在导入中包含了_ "net/http/pprof"
,并且我已经运行了HTTP服务器:
router := createRouter()
server := &http.Server {
Addr: ":8080",
Handler: router,
ReadTimeout: 15*time.Second,
WriteTimeout: 15*time.Second,
// MaxHeaderBytes: 4096,
}
log.Fatal(server.ListenAndServe())
当我尝试访问http://localhost:8080/debug/pprof/时,我得到了404页面未找到
的错误。
这是在本地机器上使用go tool pprof
时的输出:
userver@userver:~/Desktop/gotest$ go tool pprof http://192.168.0.27:8080/
Use of uninitialized value $prefix in concatenation (.) or string at /usr/lib/go/pkg/tool/linux_amd64/pprof line 3019.
Read http://192.168.0.27:8080/pprof/symbol
Failed to get the number of symbols from http://192.168.0.27:8080/pprof/symbol
userver@userver:~/Desktop/gotest$ go tool pprof http://localhost:8080/debug/pprof/profile
Read http://localhost:8080/debug/pprof/symbol
Failed to get the number of symbols from http://localhost:8080/debug/pprof/symbol
对于远程客户端也是一样的:
MacBookAir:~ apple$ go tool pprof http://192.168.0.27:8080/
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.
Read http://192.168.0.27:8080/pprof/symbol
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:
router := createRouter()
server := &http.Server {
Addr: ":8080",
Handler: router,
ReadTimeout: 15*time.Second,
WriteTimeout: 15*time.Second,
// MaxHeaderBytes: 4096,
}
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:
userver@userver:~/Desktop/gotest$ go tool pprof http://192.168.0.27:8080/
Use of uninitialized value $prefix in concatenation (.) or string at /usr/lib/go/pkg/tool/linux_amd64/pprof line 3019.
Read http://192.168.0.27:8080/pprof/symbol
Failed to get the number of symbols from http://192.168.0.27:8080/pprof/symbol
userver@userver:~/Desktop/gotest$ go tool pprof http://localhost:8080/debug/pprof/profile
Read http://localhost:8080/debug/pprof/symbol
Failed to get the number of symbols from http://localhost:8080/debug/pprof/symbol
Same for a remote client:
MacBookAir:~ apple$ go tool pprof http://192.168.0.27:8080/
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.
Read http://192.168.0.27:8080/pprof/symbol
Failed to get the number of symbols from http://192.168.0.27:8080/pprof/symbol
答案1
得分: 29
net/http/pprof
在文档中没有明确提到,但它只会将处理程序注册到http.DefaultServeMux
中。
从源代码中可以看到:
func init() {
http.Handle("/debug/pprof/", http.HandlerFunc(Index))
http.Handle("/debug/pprof/cmdline", http.HandlerFunc(Cmdline))
http.Handle("/debug/pprof/profile", http.HandlerFunc(Profile))
http.Handle("/debug/pprof/symbol", http.HandlerFunc(Symbol))
http.Handle("/debug/pprof/trace", http.HandlerFunc(Trace))
}
如果你没有使用默认的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:
func init() {
http.Handle("/debug/pprof/", http.HandlerFunc(Index))
http.Handle("/debug/pprof/cmdline", http.HandlerFunc(Cmdline))
http.Handle("/debug/pprof/profile", http.HandlerFunc(Profile))
http.Handle("/debug/pprof/symbol", http.HandlerFunc(Symbol))
http.Handle("/debug/pprof/trace", http.HandlerFunc(Trace))
}
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
处理。
import _ "net/http/debug"
router := mux.NewRouter()
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
.
import _ "net/http/debug"
router := mux.NewRouter()
router.PathPrefix("/debug/").Handler(http.DefaultServeMux)
答案3
得分: 14
看起来问题出在我在http.Server
实例中使用的github.com/gorilla/mux
中的*mux.Router
上的Handler
。
解决方案:只需再启动一个服务器用于pprof
:
server := &http.Server {
Addr: ":8080",
Handler: router,
ReadTimeout: 15*time.Second,
WriteTimeout: 15*time.Second,
}
go func() {
log.Println(http.ListenAndServe(":6060", nil))
}()
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
:
server := &http.Server {
Addr: ":8080",
Handler: router,
ReadTimeout: 15*time.Second,
WriteTimeout: 15*time.Second,
}
go func() {
log.Println(http.ListenAndServe(":6060", nil))
}()
log.Fatal(server.ListenAndServe())
答案4
得分: 3
以下是如何将pprof与Gorilla mux结合使用的方法。为了避免HTTP 404错误,我们需要显式指定**/debug/pprof/{cmd}
**的路由,因为Gorilla不会进行前缀路由:
router := mux.NewRouter()
router.Handle("/debug/pprof/", http.HandlerFunc(pprof.Index))
router.Handle("/debug/pprof/cmdline", http.HandlerFunc(pprof.Cmdline))
router.Handle("/debug/pprof/profile", http.HandlerFunc(pprof.Profile))
router.Handle("/debug/pprof/symbol", http.HandlerFunc(pprof.Symbol))
router.Handle("/debug/pprof/trace", http.HandlerFunc(pprof.Trace))
router.Handle("/debug/pprof/{cmd}", http.HandlerFunc(pprof.Index)) // Gorilla mux的特殊处理
err := http.ListenAndServe("127.0.0.1:9999", router)
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:
router := mux.NewRouter()
router.Handle("/debug/pprof/", http.HandlerFunc(pprof.Index))
router.Handle("/debug/pprof/cmdline", http.HandlerFunc(pprof.Cmdline))
router.Handle("/debug/pprof/profile", http.HandlerFunc(pprof.Profile))
router.Handle("/debug/pprof/symbol", http.HandlerFunc(pprof.Symbol))
router.Handle("/debug/pprof/trace", http.HandlerFunc(pprof.Trace))
router.Handle("/debug/pprof/{cmd}", http.HandlerFunc(pprof.Index)) // special handling for Gorilla mux
err := http.ListenAndServe("127.0.0.1:9999", router)
log.Errorf("pprof server listen failed: %v", err) // note: http.ListenAndServe never returns nil
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论