Maison  >  Article  >  développement back-end  >  Pourquoi les requêtes de publication http me permettent-elles d'utiliser beaucoup de mémoire ?

Pourquoi les requêtes de publication http me permettent-elles d'utiliser beaucoup de mémoire ?

PHPz
PHPzavant
2024-02-14 15:24:08890parcourir

为什么 http post 请求在 go 中给我带来很高的内存使用率?

L'éditeur PHP Xinyi a découvert le problème de l'utilisation élevée de la mémoire lors de l'utilisation du langage Go pour effectuer des requêtes de publication http. Cette question a déclenché sa réflexion, pourquoi cela arrive-t-il ? Après recherche et analyse, il a trouvé quelques causes possibles et proposé des solutions. Dans cet article, nous approfondirons cette question et apporterons une réponse.

Contenu de la question

J'ai une application go exécutée dans un conteneur k8s. Il fonctionne comme une API de repos, recevant des requêtes et les écrivant dans elasticsearch.

Mon code est :

var r = gin.default()
r.post("/logs", func(c *gin.context) {
        fmt.println("receive log event")
        printmemusage()
        jsondata, err := ioutil.readall(c.request.body)
        d := strings.newreader(jsondata)
        http.post(fmt.sprintf("%s/_bulk", geteshost()), "application/json", d)
        ...
    })
}


Dans le code ci-dessus, qui écoute les appels path /logs 并调用 http 将数据保存到 elasticsearch 中。当我使用下面的函数打印内存使用情况时,我可以看到 alloc 不断增加,直到内存耗尽。如果我删除 http.post, l'utilisation de la mémoire est toujours de 1 à 3 Mo. Quelle pourrait être la raison de l’utilisation croissante de la mémoire ?

func bToMb(b uint64) uint64 {
    return b / 1024 / 1024
}
func PrintMemUsage() {
    var m runtime.MemStats
    runtime.ReadMemStats(&m)
    // For info on each, see: https://golang.org/pkg/runtime/#MemStats
    fmt.Printf("Alloc = %v MiB", bToMb(m.Alloc))
    fmt.Printf("\tTotalAlloc = %v MiB", bToMb(m.TotalAlloc))
    fmt.Printf("\tSys = %v MiB", bToMb(m.Sys))
    fmt.Printf("\tNumGC = %v\n", m.NumGC)
}

Solution

documentation httpmentionnée à plusieurs reprises :

Le client doit fermer le corps de la réponse une fois terminé :

Voici un exemple tiré de la documentation :

resp, err := http.Get("http://example.com/")
if err != nil {
    // handle error
}
defer resp.Body.Close()
body, err := io.ReadAll(resp.Body)
// ...

Si vous ne le faites pas, des fuites se produiront car le corps restera en mémoire pour toujours.

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration:
Cet article est reproduit dans:. en cas de violation, veuillez contacter admin@php.cn Supprimer