英文:
Profiling Go web application built with Gorilla's mux with net/http/pprof
问题
我有一个用Go编写的相对较大的Web应用程序,使用Gorilla的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)
}
英文:
I have a relatively big web application written in Go that uses Gorilla's mux for routing. I recently realised that my web application is quite slow and I would like to profile the web application.
After reading about it, it seems that net/http/pprof is what I need. But I can't make it run with mux; even in the case of the most trivial web application.
Does anyone knows how to make that work?
Here is an example of a trivial code that does not work (i.e. nothing is served at /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)
}
答案1
得分: 36
我个人偏好的方法是让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)
}
}
我发现这种方法比依赖于隐藏初始化方法的实现更稳定,而且可以确保你没有漏掉任何东西。
英文:
My preferred method for this is to just let net/http/pprof
register itself to http.DefaultServeMux
, and then pass all requests starting with /debug/pprof/
along:
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)
}
}
I find that this approach is a lot more stable than one that depends on the implementation of a hidden initialization method, and also guarantees that you didn't miss anything.
答案2
得分: 34
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)
// 手动添加对由索引页面链接的路径的支持,路径为 /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"))
}
...
如果有其他人遇到同样的问题,希望这能帮到他们!
英文:
user983716 - Thanks for your question and solution!
I was not able to use the links from the web index (http://[my-server]/debug/pprof), until I added a few lines to your solution, like so:
...
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"))
}
...
If anyone has the same problem, I hope this helps!
答案3
得分: 14
抱歉,我只能提供中文翻译。以下是您提供的代码的翻译:
抱歉,对于那个问题。答案在pprof的init()函数中。只需要将4个函数从pprof
添加到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)
}
希望对您有所帮助!
英文:
Sorry for that question. The answer is in the init() function of pprof. One just need to add 4 functions from pprof
to the mux router. Here is the fixed code from above.
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)
}
答案4
得分: 6
我做了其他的事情,我在不同的端口上添加了另一个本地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上运行。
英文:
I did something else, I added another native http server on a different port and it just works out of the box
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()))
}
Now the pprof endpoint is at :
http://localhost:6060/debug/pprof/ and the applcation is running on port :8080
答案5
得分: 5
之前的示例在我的环境中并没有真正起作用。
要在现有的golang项目中使用gorrila/mux和pprof,请尝试添加以下代码:
...之前的代码
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/。
英文:
Previous examples not really work on my side.
To use pprof in an existing golang project with gorrila/mux, try to add :
...previous code
func main() {
r := mux.NewRouter()
r.HandleFunc("/hello", SayHello)
go func() {
log.Fatal(http.ListenAndServe(":6061", http.DefaultServeMux))
}()
http.ListenAndServe(":6060", r)
}
then go to http://localhost:6061/debug/pprof/
答案6
得分: 2
只是这样:
r := mux.NewRouter()
r.PathPrefix("/debug").Handler(http.DefaultServeMux)
英文:
Just so:
r := mux.NewRouter()
r.PathPrefix("/debug").Handler(http.DefaultServeMux)
答案7
得分: 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的回答的结合。
英文:
Im using https://github.com/julienschmidt/httprouter but i just got this answer from google search.
That's what i did
router := httprouter.New()
router.Handler("GET", "/debug/pprof/profile", http.DefaultServeMux)
router.Handler("GET", "/debug/pprof/heap", http.DefaultServeMux)
I only need this two routes.
This answer is combine of @damien and @user983716 answers.
答案8
得分: 0
以下代码应该可以工作:
import (
"net/http"
_ "net/http/pprof"
)
myrouter.PathPrefix("/debug/pprof/").Handler(http.DefaultServeMux)
这段代码导入了"net/http"和"net/http/pprof"包,并使用myrouter.PathPrefix
将"/debug/pprof/"路径的请求交给了http.DefaultServeMux
处理。
英文:
The following should work:
import (
"net/http"
_ "net/http/pprof"
)
myrouter.PathPrefix("/debug/pprof/").Handler(http.DefaultServeMux)
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论