我正在向API发送大约100,000个JSON对象的列表,该API只能一个接一个地接受它们,并且我以异步方式发送它们。我知道API在内部将接收到的对象发送到一个队列,该队列似乎被所有这些请求阻塞了,导致我在经过许多请求后收到“网关超时”错误。
我尝试将列表拆分成不同大小的批次,并在发送每个批次后将线程置于睡眠状态,但最终发生的结果是,它在大约批量大小时失败并出现相同的错误,我尝试了批次3000、2500和1000具有相同的结果,并且线程似乎从未进入睡眠状态。
这是有问题的代码:
public async Task TransferData(IEnumerable<MyData> data)
{
var pages = Math.Ceil(data.Count() / 3000m);
for (var page = 0; page < pages; page++)
{
await TransferPage(data.Skip(page * 3000).Take(3000);
Thread.Sleep(10000);
}
}
private async Task TransferPage(IEnumerable<MyData> data)
{
await Task.WhenAll(data.Select(p => webConnection.PostDataAsync(JsonConvert.SerializeObject(p, Formatting.None))));
}
注意:webConnection只是一个类,该类具有已实例化的HttpClient,并执行PostAsync将数据发送到预期的URL。
对TransferData的调用是在控制台应用程序中完成的,如下所示:
try
{
...
dataManager.TransferData(data).Wait();
}
catch(AggregateException ex)
{
...
}
catch(Exception ex)
{
...
}
谢谢您的指导。
更新:澄清在评论中引起的一些混淆。外部API正在一个接一个地接收对象,如果您在WhileAll IEnumerable具有Select的内部查看私有方法TransferPage ,则该方法将对内部执行实际HttpClient PostAsync的方法的调用进行选择。因此,将对象按批进行分组,并在每批中将它们一一发送。我希望这可以使它更加清楚。
答案 0 :(得分:0)
可能发生的情况是,一个或多个PostDataAsync
任务引发超时错误,从而导致任务失败。 Task.WhenAll
仅将它们捆绑成一个AggregateException
,并在列表中的所有任务完成后将其抛出,这就是为什么只在批处理结束时看到异常的原因。
尽管您试图节流,但您仍可能不堪重负。您可能应该做几件事:
PostDataAsync
内部和/或外部执行此操作。即使您没有压倒性的服务,您仍然需要处理临时异常以应对网络故障等。SemaphoreSlim
或TPL Dataflow是常见的解决方案。