我有一個 .netcore 6 BackGroundService,它將資料從本地推送到第 3 方 API。
第 3 方 API 需要大約 500 毫秒來處理 API 呼叫。
問題是我有大約 1,000,000 行資料要一次推送到這個 API。在每行 1/2 秒的情況下,同步大約需要 6 天。
所以,我想嘗試生成多個執行緒,以便用 10 個執行緒同時訪問 API。
var startTime = DateTimeOffset.Now;
var batchSize = _config.GetValue<int>("BatchSize");
using (var scope = _serviceScopeFactory.CreateScope())
{
var context = scope.ServiceProvider.GetRequiredService<PlankContext>();
var dncEntries = await context.PlankQueueDnc.Where(x => x.ToProcessFlag == true).Take(batchSize).ToListAsync();
foreach (var plankQueueDnc in dncEntries)
{
var response = await _plankConnector.InsertDncAsync(plankQueueDnc);
context.PlankQueueDnc.Update(plankQueueDnc);
}
await context.SaveChangesAsync();
}
這是代碼。如您所見,它獲取了一批 100 條記錄,然后逐條處理它們。有沒有辦法修改這個,所以這條線不被等待?我不太明白如果不等待它會如何作業。它會為回圈中的每個執行創建一個執行緒嗎?
var response = await _plankConnector.InsertDncAsync(plankQueueDnc);
我顯然跟不上執行緒以及受人尊敬的@StephanCleary 的速度。
所以建議將不勝感激。
uj5u.com熱心網友回復:
在 .NET 6 中,您可以使用 Parallel.ForEachAsync 并發執行操作,使用所有可用內核或有限的并行度。
以下代碼加載所有記錄,并發執行帖子,然后更新記錄:
using (var scope = _serviceScopeFactory.CreateScope())
{
var context = scope.ServiceProvider.GetRequiredService<PlankContext>();
var dncEntries = await context.PlankQueueDnc
.Where(x => x.ToProcessFlag == true)
.Take(batchSize)
.ToListAsync();
await Parallel.ForEachAsync(dncEntries,async plankQueueDnc=>
{
var response = await _plankConnector.InsertDncAsync(plankQueueDnc);
plankQueueDnc.Whatever=response.Something;
};
await context.SaveChangesAsync();
}
沒有理由呼叫UpdateDbContext 跟蹤它加載的物件并知道哪些物件被修改。SaveChangesAsync將在單個事務中保留所有更改
DOP 和節流
默認情況下,ParallelForEachAsync 將同時執行與核心數量一樣多的任務。對于 HTTP 呼叫,這可能太少或太多。一方面,客戶端機器在等待遠程服務時根本沒有使用它的 CPU。另一方面,遠程服務本身可能不喜歡甚至不允許太多并發呼叫,甚至可能會施加限制。
ParallelOptions類可用于指定并行度。如果 API 允許,我們可以執行例如 20 個并發呼叫:
var option=new ParallelOptions { MaxDegreeOfParallelism = 20};
await Parallel.ForEachAsync(dncEntries,options,async plankQueueDnc=>{...});
許多服務對在一段時間內可以發出多少請求施加一個速率。一種(有點幼稚的)實作方式是在任務作業者代碼中添加一個小的延遲可以解決這個問題:
var delay=100;
await Parallel.ForEachAsync(dncEntries,options,async plankQueueDnc=>{
...
await Task.Delay(delay);
});
轉載請註明出處,本文鏈接:https://www.uj5u.com/gongcheng/422417.html
標籤:
