所以我试图从http.Response中获取响应主体,进行一些操作,然后将其设置回来。这是我第一次尝试将其删除而不会耗尽http.Response:
<?php
$username = 'username';
$password = 'pass';
$host = 'localhost';
$dbname = 'db';
try {
$dbh = new PDO("mysql:host=$host;dbname=$dbname", $username, $password);
// set the PDO error mode to exception
$dbh->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$stmt = $dbh->prepare("INSERT INTO table1 (issue, time, comments, lat, lng) VALUES (:issue, :time, :comments, :lat, :lng)");
$stmt->bindParam(':issue', $issue);
$stmt->bindParam(':time', $time);
$stmt->bindParam(':comments', $comments);
$stmt->bindParam(':lat', $lat);
$stmt->bindParam(':lng', $lng);
$stmt->execute();
header("Location: main.php");
}
catch(PDOException $e)
{
echo "Error: " . $e->getMessage();
}
$dbh = null;
?>
如果我发送500个请求,响应大小为1mb(一大块JSON,但它可能是任何格式,不仅是JSON),服务器内存使用量上升到〜400mb,并且不会回来了。这是正常的吗?上面的代码有问题吗?我错过了释放记忆的东西吗?
延迟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
答案 0 :(得分:3)
使用后必须关闭身体。请参阅this
请注意,在您使用新值重新分配defer resp.Body.Close()
后,系统会调用resp.Body
。
答案 1 :(得分:2)
ioutil.NopCloser
使Close()
无所作为。如果你推迟关闭,你永远不会真正关闭它。在阅读后立即关闭。
bodyBytes, err := ioutil.ReadAll(resp.Body)
if err != nil {
// err
}
resp.Body.Close()
cachedBody := string(bodyBytes)
// Close() does nothing after this
resp.Body = ioutil.NopCloser(bytes.NewBuffer(bodyBytes))
同样在Go中,您通常可以忽略该else
,因为您可能应该返回错误或在其上方if
处理错误。
这样的事情也很适合拥有sync.Pool
,因为你继续回收大量的缓冲区,检查它在net/http
包中的使用方式。