簡體   English   中英

如何盡快有效地發出 1000 多個 Web 請求

[英]How to efficiently make 1000s of web requests as quickly as possible

我需要從 C# 控制台應用程序發出 100,000 個輕量級(即小的 Content-Length)Web 請求。 最快的方法是什么(即在盡可能短的時間內完成所有請求)以及我應該遵循哪些最佳實踐? 我不能開火就忘記,因為我需要捕捉反應。

大概我想使用async Web 請求方法,但是我想知道存儲所有Task延續和編組的開銷會產生什么影響。

內存消耗不是一個整體問題,目標是速度。

大概我還想利用所有可用的內核。

所以我可以這樣做:

Parallel.ForEach(iterations, i =>
{
    var response = await MakeRequest(i);
    // do thing with response
});

但這不會讓我比我的核心數量更快。

我可以:

Parallel.ForEach(iterations, i =>
{
    var response = MakeRequest(i);
    response.GetAwaiter().OnCompleted(() =>
    {
        // do thing with response
    });
});

但是如何讓我的程序在ForEach之后運行。 堅持所有的TasksWhenAll ing 他們感覺臃腫,是否有任何現有的模式或助手來擁有某種任務隊列?

有什么辦法可以改善,我應該如何處理節流/錯誤檢測? 例如,如果遠程端點響應緩慢,我不想繼續向它發送垃圾郵件。

我明白我還需要做:

ServicePointManager.DefaultConnectionLimit = int.MaxValue

還有什么必要的嗎?

Parallel類不適用於異步循環體,因此您不能使用它。 您的循環體幾乎立即完成並返回一個任務。 這里沒有並行性好處。

這是一個非常簡單的問題。 使用一種標准解決方案來使用給定的 DOP 異步處理一系列項目(這個很好:http: //blogs.msdn.com/b/pfxteam/archive/2012/03/05/10278165.aspx 。使用最后一段代碼)。

您需要憑經驗確定正確的 DOP。 只需嘗試不同的值。 沒有理論上的方法可以得出最佳價值,因為它取決於很多因素。

連接限制是您的唯一限制。

response.GetAwaiter().OnCompleted

不確定你在那里試圖完成什么......如果你發表評論,我會解釋誤解。

您要執行的操作是

  1. 調用 I/O 方法
  2. 處理結果

您應該使用 I/O 方法的async版本是正確的。 更重要的是,您只需要 1 個線程即可啟動所有 I/O 操作。 您不會在這里受益於並行性。

您將受益於第二部分的並行性 - 處理結果,因為這將是一個 CPU 密集型操作。 幸運的是, async / await將為您完成所有工作。 控制台應用程序沒有同步上下文。 這意味着await之后的方法部分將在線程池線程上運行,以最佳方式利用所有 CPU 內核。

private async Task MakeRequestAndProcessResult(int i)
{
    var result = await MakeRequestAsync();
    ProcessResult(result);
}

var tasks = iterations.Select(i => MakeRequestAndProcessResult(i)).ToArray();

要在具有同步上下文(例如 WPF 或 WinForms)的環境中實現相同的行為,請使用ConfigureAwait(false)

var result = await MakeRequestAsync().ConfigureAwait(false);

要等待任務完成,您可以在async方法中使用await Task.WhenAll(tasks)或在Main() Task.WaitAll(tasks)

向 Web 服務發出 100k 請求可能會殺死它,因此您必須對其進行限制。 您可以檢查此問題的答案以找到一些選項如何做到這一點。

如果您顯式設置 ParallelOptions 參數的 MaxDegreeOfParallelism 屬性(在有該參數的 ForEach 的重載中),Parallel.ForEach 應該能夠使用比內核更多的線程 - 請參閱https://msdn.microsoft.com/en -us/library/system.threading.tasks.paralleloptions.maxdegreeofparallelism(v=vs.110).aspx

您應該能夠將其設置為 1,000 以使其使用 1,000 個線程或更多,但由於線程開銷,這可能效率不高。 您可能希望進行實驗(例如,從 100 步循環到 1,000 步,每 100 秒嘗試每次提交 1,000 個請求,並且從開始到結束)或者甚至設置某種自調整算法。

暫無
暫無

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

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