简体   繁体   English

如何在异步任务 C# 中限制每秒请求

[英]How to Limit request per Second in Async Task C#

I'm writing an application which interact with Azure Cosmos DB.我正在编写一个与 Azure Cosmos DB 交互的应用程序。 I need commit 30,000 Records to CosmosDB in a Session.我需要在一个会话中向 CosmosDB 提交 30,000 条记录。 Because I used .NET Core so I cannot use BulkInsert dll.因为我使用了 .NET Core,所以我不能使用 BulkInsert dll。 So, I use Foreach loop to Insert to CosmosDB.所以,我使用 Foreach 循环插入到 CosmosDB。 But I see too many request per Second and it overload RU limit by CosmosDB.但是我看到每秒请求太多,并且 CosmosDB 超过了 RU 限制。

foreach(item in listNeedInsert){
      await RequestInsertToCosmosDB(item);
}

I want to Pause foreach loop when Number of request reach 100. After done 100 request.我想在请求数达到 100 时暂停 foreach 循环。完成 100 个请求后。 foreach will continue. foreach 将继续。

You can partition the list and await the results: 您可以对列表进行分区并等待结果:

var tasks = new List<Task>();

foreach(item in listNeedInsert)
{
    var task = RequestInsertToCosmosDB(item);
    tasks.Add(task);

    if(tasks.Count == 100)
    {
        await Task.WhenAll(tasks);
        tasks.Clear();
    }
}

// Wait for anything left to finish
await Task.WhenAll(tasks);

Every time you've got 100 tasks running the code will wait for them all to finish before executing the last batch. 每次您有100个任务运行时,代码将等待它们全部完成,然后再执行最后一批。

You could set a delay on every hundred iteration 您可以在每一百次迭代中设置一个延迟

int i = 1;
foreach(item in listNeedInsert)
{
      await RequestInsertToCosmosDB(item);
      if (i % 100 == 0)
      {
          i = 0;
          await Task.Delay(100); // Miliseconds
      }
      i++;
}

If you really want to maximize efficiency and can't do bulk updates, look into using SemaphorSlim in this post: 如果您确实想最大化效率并且不能进行批量更新,请在本文中研究使用SemaphorSlim:

Throttling asynchronous tasks 节流异步任务

Hammering a medium-sized database with 100 concurrent requests at a time isn't a great idea because it's not equipped to handle that kind of throughput. 一次敲打一个具有100个并发请求的中型数据库不是一个好主意,因为它没有能力处理这种吞吐量。 You could try playing with a different throttling number and seeing what's optimal, but I would guess it's in the single digit range. 您可以尝试使用不同的调节数字并查看最佳值,但我想这是个位数的范围。

If you want to do something quick and dirty, you could probably use Sean's solution. 如果您想快速又肮脏地做某事,则可以使用Sean的解决方案。 But I'd set the Task count to 5 starting out, not 100. 但是我将任务计数设置为5,而不是100。

https://github.com/thomhurst/EnumerableAsyncProcessor https://github.com/thomhurst/EnumerableAsyncProcessor

I've written a library to help with this sort of logic.我编写了一个库来帮助处理这种逻辑。

Usage would be:用法是:

await AsyncProcessorBuilder.WithItems(listNeedInsert) // Or Extension Method: listNeedInsert.ToAsyncProcessorBuilder()
        .ForEachAsync(item => RequestInsertToCosmosDB(item), CancellationToken.None)
        .ProcessInBatches(batchSize: 100);

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM