[英]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
之后運行。 堅持所有的Tasks
和WhenAll
ing 他們感覺臃腫,是否有任何現有的模式或助手來擁有某種任務隊列?
有什么辦法可以改善,我應該如何處理節流/錯誤檢測? 例如,如果遠程端點響應緩慢,我不想繼續向它發送垃圾郵件。
我明白我還需要做:
ServicePointManager.DefaultConnectionLimit = int.MaxValue
還有什么必要的嗎?
Parallel
類不適用於異步循環體,因此您不能使用它。 您的循環體幾乎立即完成並返回一個任務。 這里沒有並行性好處。
這是一個非常簡單的問題。 使用一種標准解決方案來使用給定的 DOP 異步處理一系列項目(這個很好:http: //blogs.msdn.com/b/pfxteam/archive/2012/03/05/10278165.aspx 。使用最后一段代碼)。
您需要憑經驗確定正確的 DOP。 只需嘗試不同的值。 沒有理論上的方法可以得出最佳價值,因為它取決於很多因素。
連接限制是您的唯一限制。
response.GetAwaiter().OnCompleted
不確定你在那里試圖完成什么......如果你發表評論,我會解釋誤解。
您要執行的操作是
您應該使用 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.