在 go lang 中分析 http 处理程序

profiling http handler in go lang

我正在尝试分析我用 go 编写的 http 处理程序。在每个 http 请求上从 S3 下载图像,调整大小 it/crop 并将其写入响应。

我已遵循此 link 并尝试使用简单方法和困难方法来分析我的代码。现在,当我使用代码中提到的以下行时。

defer profile.Start(profile.CPUProfile).Stop() 

它没有在 /tmp/profie[some number]/cpu.pprof 文件中写入任何内容

func main() {                                    

       defer profile.Start(profile.CPUProfile).Stop()   

      if err := http.ListenAndServe(":8081", http.HandlerFunc(serveHTTP)); err != nil {
       logFatal("Error when starting or running http server: %v", err)
    }       
}

func serveHTTP(w http.ResponseWriter, r *http.Request) {
        keyName := r.URL.Path[1:]
        s3Client := s3.New(session.New(), &aws.Config{Region: aws.String(region)})
        params := &s3.GetObjectInput{
        Bucket: aws.String(bucketName),
        Key: aws.String(keyName),
        }

    mw := imagick.NewMagickWand()
    defer mw.Destroy()
    ...
}

此外,当我在 serveHTTP 中使用 defer profile.Start(profile.CPUProfile).Stop() 行时,例如:

func serveHTTP(w http.ResponseWriter, r *http.Request) {

    defer profile.Start(profile.CPUProfile).Stop()
    ......
}

它在 /tmp/profile[some number] 文件夹中创建了多个文件。所以,第一个问题是为什么它不写入文件,其次它不应该放在 serveHTTP method 内,因为服务器只会启动一次。因此 main() 将被调用一次,而 serveHTTP 将在每次请求时被调用。

第 1 部分

 .               124:   s3Client := s3.New(session.New(), &aws.Config{Region: aws.String(region)})
 .          .    125:        params := &s3.GetObjectInput{
 .          .    126:       Bucket: aws.String(masterBucketName),
 .          .    127:       Key: aws.String(keyName),
 .    32.01kB    128:       }
 .          .    129:
 .          .    130:   mw := imagick.NewMagickWand()
 .          .    131:   defer mw.Destroy()
 .          .    132:   
 .          .    133:   out, err := s3Client.GetObject(params)          
 .          .    134:
 .          .    135:   if strings.EqualFold(keyName[strings.LastIndex(keyName,".")+1:len(keyName)], "gif") {
 .          .    136:
 .    40.11kB    137:       blobGiff, err := ioutil.ReadAll(out.Body)
 .          .    138:       w.Header().Set("Content-Type", "image/gif")
 .          .    139:       w.Header().Set("Cache-Control", "max-age: 604800, public")  
 .          .    140:       w.Header().Set("Last-Modified", time.Now().Format(http.TimeFormat))
 .          .    141:       w.Header().Set("Expires", time.Now().AddDate(1, 0, 0).Format(http.TimeFormat))  
 .          .    142:

第 2 部分:

                                   else {
         .          .    167:       img, err := ioutil.ReadAll(out.Body)
         .          .    168:       if err != nil {
         .          .    169:          
         .          .    170:          w.WriteHeader(http.StatusNotFound) 
         .     1.56MB    171:          return      
         .          .    172:       }   

另外,上面两部分128、137、171行有内存泄漏,对吧?此外,我没有找到 close/destroy s3ClientblobGiff(字节 [])的任何选项。

要在 运行 时分析 http 服务器,您可以使用 net/http/pprof 包。

只需添加

import _ "net/http/pprof"

导入并在浏览器中打开 http://localhost:8081/debug/pprof/

首先使用import "net/http/pprof" NOT import _ "net/http/pprof。后来有人没认出下面路由中的pprof .

我使用的是默认值 serveMux/multiplexer。但后来我创建了自己的,因为人们认为它具有性能影响。

myMux := http.NewServeMux()

然后添加请求的路由

myMux.HandleFunc("/", serveHTTP)

此外,我还添加了使 http://localhost:8081/debug/pprof/ 工作的路由

        myMux.HandleFunc("/debug/pprof/", pprof.Index)
        myMux.HandleFunc("/debug/pprof/{action}", pprof.Index)
        myMux.HandleFunc("/debug/pprof/symbol", pprof.Symbol)

因此,最终代码将是:

导入“net/http/pprof

func main() {                                    
        
        myMux := http.NewServeMux()
        myMux.HandleFunc("/", serveHTTP)

        myMux.HandleFunc("/debug/pprof/", pprof.Index)
        myMux.HandleFunc("/debug/pprof/{action}", pprof.Index)
        myMux.HandleFunc("/debug/pprof/symbol", pprof.Symbol)   

    if err := http.ListenAndServe(":8081", myMux); err != nil {
        logFatal("Error when starting or running http server: %v", err)
    }       

}