分析 HTTP 服务
如您在第11章(代码测试,优化和分析)中了解到的,有个名为 net/http/pprof
标准包,当您想要用它自己的 HTTP 服务分析一个 Go 应用时,可以使用它。因此,导入 net/http/pprof
将在 /debug/pprof/
URL 下安装各种处理程序。您很快就会看到更多的情况。现在,您记住 net/http/pprof
包应该用于用 HTTP 服务分析 web 应用就足够了,而 runtime/pprof
标准包应该用于分析其他类型的应用。
注意,如果您的分析器工作在 http://localhost:8080
地址,您将从 如下 web 链接获得支持:
- http://localhost:8080/debug/pprof/goroutine
- http://localhost:8080/debug/pprof/heap
- http://localhost:8080/debug/pprof/theadcreate
- http://localhost:8080/debug/pprof/block
- http://localhost:8080/debug/pprof/mutex
- http://localhost:8080/debug/pprof/profile
- http://localhost:8080/debug/pprof/trace?seconds=5
下面被展示的程序将使用 www.go
做为起始点,并添加必要的 Go 代码允许您去分析它。这个新程序命名为 wwwProfile.go
,分为四部分展示。
注意,wwwProfile.go
将使用一个 http.NewServeMux
变量用于注册程序支持的路径。这样做的主要原因是,使用 http.NewServeMux
需要手动定义 HTTP 端点。如果您决定不使用 http.NewServeMux
,那么 HTTP 端点将自动注册,这也意味着您将使用 _
字符在引入的 net/http/pprof
包前。
wwwProfile.go
第一部分包含的 Go 代码如下:
package main
import (
"fmt"
"net/http"
"net/http/pprof"
"os"
"time"
)
func myHandler(w http.ResponseWriter, r *http.Request) {
fmt.Fprintf(w, "Serving: %s\n", r.URL.Path)
fmt.Printf("Served: %s\n", r.Host)
}
func timeHandler(w http.ResponseWriter, r *http.Request) {
t := time.Now().Format(time.RFC1123)
Body := "The current time is:"
fmt.Fprintf(w, "<h1 align=\"center\">%s</h1>", Body)
fmt.Fprintf(w, "<h2 align=\"center\">%s</h2>\n", t)
fmt.Fprintf(w, "Serving: %s\n", r.URL.Path)
fmt.Printf("Served time for: %s\n", r.Host)
}
这俩个处理函数的实现与之前的一样。
wwwProfile.go
的第二段代码如下:
func main() {
PORT := ":8001"
arguments := os.Args
if len(arguments) == 1 {
fmt.Println("Using default port number: ", PORT)
}else{
PORT = ":" + arguments[1]
fmt.Println("Using port number: ", PORT)
}
r := http.NewServeMux()
r.HandleFunc("/time", timeHandler)
r.HandleFunc("/", myHandler)
在上面的 Go 代码中,您使用 http.NewServeMux()
和 HandleFunc()
定义您的 web 服务支持的 URL。
wwwProfile.go
的第三段代码如下:
r.HandleFunc("/debug/pprof/", pprof.Index)
r.HandleFunc("/debug/pprof/cmdline", pprof.Cmdline)
r.HandleFunc("/debug/pprof/profile", pprof.Profile)
r.HandleFunc("/debug/pprof/symbol", pprof.Symbol)
r.HandleFunc("/debug/pprof/trace", pprof.Trace)
上面的 Go 代码定义与分析相关的 HTTP 端点。没有它们,您将不能分析您的 web 应用。
余下的 Go 代码如下:
err := http.ListenAndServe(PORT, r)
if err != nil {
fmt.Println(err)
return
}
}
这段代码启动 web 服务,并允许它服务来自 HTTP 客户端的连接。您会注意到 http.ListenAndServe()
的第二个参数不再是 nil
。
如您所见,wwwProfile.go
没有定义 /debug/pprof/goroutine
HTTP 端点,这意味着 wwwProfile.go
不使用任何 goroutines !
执行 wwwProfile.go
将产生如下输出:
$ go run wwwProfile.go 1234
Using port number: :1234
Served time for: localhost:1234
使用 Go 分析器获取数据是相当简单的任务,执行下面的命令将带您自动进入 Go 分析器的 shell。
如您在第11章(代码测试,优化和分析)中了解到的,您现在可以使用这个分析数据,并使用 go tool pprof
分析它。
您可以访问
http://HOSTNAME:PORTNUMBER/debug/pprof
,从那可以看到分析结果。当HOSTNAME
的值是localhost
,PORTNUMBER
的值是1234
时,您应该访问http://localhost:1234/debug/pprof/
。
您应该希望测试您的 web 服务应用的性能,您可以使用 ab(1)
工具,它做为 Apache HTTP server benchmarking tool 广为人知,用于创建流量和基准。这也允许 go tool pprof
收集更多的准确数据,如下: