http.Response.Body 复制导致内存使用量大幅增加

所以我试图从 http.Response 中获取响应正文,进行一些操作,然后将其设置回来。这是我第一次尝试在不耗尽 http.Response 的情况下将其取出:


bodyBytes, err := ioutil.ReadAll(resp.Body)

if err != nil {

    // err

} else {

    cachedBody := string(bodyBytes)


    // Restore the io.ReadCloser to its original state

    // This is causing huge increases in memory usage.

    resp.Body = ioutil.NopCloser(bytes.NewBuffer(bodyBytes))

}

如果我发送 500 个请求,响应大小为 1mb(一大块 JSON,但它可以是任何格式,不仅是 JSON),服务器内存使用量上升到约 400mb,并且不会回落。这是正常的吗?上面的代码有问题吗?我是否错过了释放记忆的东西?


defer resp.Body.Close() 没有效果。


谢谢!


编辑 1


这是代理的简单版本的要点,包括建议的近距离通话。如果位于 localhost:3000(它代理的位置)的服务器返回大量响应,内存使用量将迅速增加。就我而言,我返回一个 1mb json 文件,通过 go 代理发送 500 个请求将内存使用量增加到 400mb 左右。


Go 代理:https :

//gist.github.com/marbemac/300c4c376171cbd27cc3


一个简单的节点服务器,它在同一目录中返回一个名为 large_response.json 的文件。

https://gist.github.com/marbemac/55aaa78f5858484d33f6


精慕HU
浏览 270回答 2
2回答

PIPIONE

使用后必须关闭主体。参考这个请注意,在使用新值defer resp.Body.Close()重新分配 后会调用resp.Body。

BIG阳

ioutil.NopCloser使Close()什么都不做。如果你推迟关闭,你永远不会真正关闭它。阅读后立即关闭。bodyBytes, err := ioutil.ReadAll(resp.Body)if err != nil {    // err} resp.Body.Close()cachedBody := string(bodyBytes)// Close() does nothing after thisresp.Body = ioutil.NopCloser(bytes.NewBuffer(bodyBytes))同样在 Go 中,您通常可以忽略它,else因为您可能应该在if上面返回错误或处理它。像这样的事情有时也sync.Pool很好,因为您不断回收巨大的缓冲区,请检查它在net/http包中的使用方式作为示例。
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Go