【发布时间】:2015-09-08 05:47:33
【问题描述】:
所以我试图从 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
【问题讨论】:
-
也许这可以帮助你stackoverflow.com/questions/21080642/…试试
go prof -
嗯,这很有趣,感谢您的链接,但我不认为就是这样。这是一个突然而剧烈的增长(在几秒钟内从 6mb 开始状态到 400mb,发送了这 500 个请求)。我觉得我缺少一些东西。
-
对您在这里尝试做的事情感到困惑。当然
defer resp.Body.Close()没有效果,你把它变成ioutil.NopCloser。阅读它,在使Close()成为空操作之前关闭它,然后设置它,会发生什么? -
也许你需要在
bodyBytes, err := ioutil.ReadAll(resp.Body)之后resp.Body.Close()? -
我明白了。哪种类型的内存“上升”?很可能它根本不重要,因为这是虚拟内存。也许您可以通过
go test -benchmem和适当的基准来衡量分配,以查看您是否分配并执行真实的内存配置文件。 “内存”如 top 等人所示。上去不放出来这个没问题。
标签: go