簡體   English   中英

HttpClient內存使用量激增,響應速度很快

[英]HttpClient spike in memory usage with large response

我正在開發一個控制台應用程序,它將端點列表提供給視頻數據,發出HTTP請求,並將結果保存到文件中。 這些是相對較小的視頻。 由於我無法控制的問題,其中一個視頻非常大(145分鍾而不是幾秒鍾)。

我看到的問題是,在調用該請求后,我的內存使用率達到~1 GB,並且我最終得到“任務被取消”錯誤(可能是因為客戶端超時)。 這很好,我不想要這個視頻,但令人擔憂的是,無論我做什么,我分配的內存都會保持很高。 我希望能夠釋放內存。 似乎有點關於任務管理器在此調用之前顯示大約14 MB的內存使用量,然后繼續逐漸涓流。 在VS調試器中,我只看到一個尖峰。

我嘗試在using語句中拋出所有內容,在異常時重新初始化HttpClient ,手動調用GC.Collect()沒有運氣。 我正在使用的代碼看起來像這樣:

consumer.Received += async (model, ea) =>
{
    InitializeHttpClient(source);
    ...
    foreach(var item in queue)
    {
        await SaveFileFromEndpoint(url, fileName);
        ...
    }
}

和方法:

public void InitializeHttpClient(string source)
{
    ...
    _client = new HttpClient();
    ...
}

public async Task SaveFileFromEndpoint(string endpoint, string fileName)
{
    try
    {
        using (HttpResponseMessage response = await _client.GetAsync(endpoint))
        {
            if (response.IsSuccessStatusCode)
            {
                using(var content = await response.Content.ReadAsStreamAsync())
                using (var fileStream = File.Create($"{fileName}"))
                {
                    await response.Content.CopyToAsync(fileStream);
                }
            }
        }
    }
    catch (Exception ex)
    {

    }
}

這是我的調試器輸出:

記憶飆升

我想我對我所看到的內容有幾個問題:

  1. 我看到的內存使用量實際上是一個問題嗎?
  2. 有什么辦法可以釋放大型HTTP請求分配的內存嗎?
  3. 在調用和分配內存之前,有什么方法可以看到請求的內容長度嗎? 到目前為止,我還沒有找到一種在分配實際內存之前找到方法的方法。

在此先感謝您的幫助!

如果使用HttpClient.SendAsync(HttpRequestMessage, HttpCompletionOption)而不是GetAsync ,則可以提供HttpCompletionOption.ResponseHeadersRead (與默認的ResponseContentRead相反)。 這意味着響應流將在響應主體下載之前(而不是之后)回傳給您,並且將需要顯着更少的緩沖區來運行。

除了@splander的答案(這是關鍵的),您還需要確保在完成后處理響應。 您可以在“使用HttpClient高效流式傳輸大型HTTP響應”一文中找到有關此內容的更多信息。

這是一個代碼示例:

using (HttpClient client = new HttpClient())
{
    const string url = "https://github.com/tugberkugurlu/ASPNETWebAPISamples/archive/master.zip";
    using (HttpResponseMessage response = await client.GetAsync(url, HttpCompletionOption.ResponseHeadersRead))
    using (Stream streamToReadFrom = await response.Content.ReadAsStreamAsync())
    {
        string fileToWriteTo = Path.GetTempFileName();
        using (Stream streamToWriteTo = File.Open(fileToWriteTo, FileMode.Create))
        {
            await streamToReadFrom.CopyToAsync(streamToWriteTo);
        }
    }
}

您還需要考慮到不應該為每個操作創建一個HttpClient實例。 HttpClientFactory是一種非常有條理的方式,可確保您以最高效的方式安全地在應用程序中流動HttpClient。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM