12.7.1 分析HTTP服务

如您在第11章(代码测试,优化和分析)中了解到的,有个名为 net/http/pprof 标准包,当您想要用它自己的 HTTP 服务分析一个 Go 应用时,可以使用它。因此,导入 net/http/pprof 将在 /debug/pprof/ URL 下安装各种处理程序。您很快就会看到更多的情况。现在,您记住 net/http/pprof 包应该用于用 HTTP 服务分析 web 应用就足够了,而 runtime/pprof 标准包应该用于分析其他类型的应用。

注意,如果您的分析器工作在 http://localhost:8080 地址,您将从 如下 web 链接获得支持:

下面被展示的程序将使用 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 的值是 localhostPORTNUMBER 的值是 1234 时,您应该访问 http://localhost:1234/debug/pprof/

您应该希望测试您的 web 服务应用的性能,您可以使用 ab(1) 工具,它做为 Apache HTTP server benchmarking tool 广为人知,用于创建流量和基准。这也允许 go tool pprof 收集更多的准确数据,如下:

Last updated