.NET中的并行抓取

我工作的公司运行着几百个非常动态的网站。 它决定建立一个搜索引擎,我的任务是编写刮刀。 一些站点在旧硬件上运行,不能承受太多惩罚,而其他站点可以处理大量的并发用户。

我需要能够说对站点A使用5个并行请求,对站点B使用2个,对站点C使用1个并行请求。

我知道我可以使用线程,互斥量,信号量等来实现这一目标,但它会非常复杂。 任何更高级别的框架,如TPL,await / async,TPL Dataflow是否足够强大,能够以更简单的方式完成此应用程序?

我建议您使用HttpClientTask.WhenAll ,使用SemaphoreSlim进行简单的限制:

 private SemaphoreSlim _mutex = new SemaphoreSlim(5); private HttpClient _client = new HttpClient(); private async Task DownloadStringAsync(string url) { await _mutex.TakeAsync(); try { return await _client.GetStringAsync(url); } finally { _mutex.Release(); } } IEnumerable urls = ...; var data = await Task.WhenAll(urls.Select(url => DownloadStringAsync(url)); 

或者,您可以使用TPL Dataflow并将MaxDegreeOfParallelism设置为限制。

TPL Dataflowasync-await确实非常强大和简单,能够满足您的需求:

 async Task> GetAllStringsAsync(IEnumerable urls) { var client = new HttpClient(); var bag = new ConcurrentBag(); var block = new ActionBlock( async url => bag.Add(await client.GetStringAsync(url)), new ExecutionDataflowBlockOptions {MaxDegreeOfParallelism = 5}); foreach (var url in urls) { block.Post(url); } block.Complete(); await block.Completion; return bag; }